diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java index 7cfc79835b..3d3987aca3 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java @@ -2,14 +2,11 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; -import org.jboss.resteasy.spi.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.ArgumentCaptor; @@ -27,6 +24,7 @@ import sonia.scm.repository.RepositoryManager; import sonia.scm.store.ConfigurationStore; import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.web.GitVndMediaType; +import sonia.scm.web.ScmTestDispatcher; import javax.servlet.http.HttpServletResponse; import java.io.UnsupportedEncodingException; @@ -52,10 +50,7 @@ public class GitConfigResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); @@ -89,7 +84,7 @@ public class GitConfigResourceTest { when(repositoryHandler.getConfig()).thenReturn(gitConfig); GitRepositoryConfigResource gitRepositoryConfigResource = new GitRepositoryConfigResource(repositoryConfigMapper, repositoryManager, new GitRepositoryConfigStoreProvider(configurationStoreFactory)); GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, of(gitRepositoryConfigResource)); - dispatcher.getRegistry().addSingletonResource(gitConfigResource); + dispatcher.addSingletonResource(gitConfigResource); when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @@ -137,10 +132,11 @@ public class GitConfigResourceTest { @Test @SubjectAware(username = "writeOnly") - public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException { - thrown.expectMessage("Subject does not have permission [configuration:read:git]"); + public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { + MockHttpResponse response = get(); - get(); + assertEquals("Subject does not have permission [configuration:read:git]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -152,10 +148,11 @@ public class GitConfigResourceTest { @Test @SubjectAware(username = "readOnly") - public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException { - thrown.expectMessage("Subject does not have permission [configuration:write:git]"); + public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { + MockHttpResponse response = put(); - put(); + assertEquals("Subject does not have permission [configuration:write:git]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResourceTest.java index 21da84e7ec..fa2b559041 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigAutoConfigurationResourceTest.java @@ -2,14 +2,11 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; -import org.jboss.resteasy.spi.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.ArgumentCaptor; import org.mockito.InjectMocks; @@ -18,12 +15,15 @@ import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.repository.HgConfig; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.web.HgVndMediaType; +import sonia.scm.web.ScmTestDispatcher; import javax.inject.Provider; import javax.servlet.http.HttpServletResponse; import java.net.URISyntaxException; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -37,10 +37,7 @@ public class HgConfigAutoConfigurationResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @InjectMocks private HgConfigDtoToHgConfigMapperImpl dtoToConfigMapper; @@ -57,7 +54,7 @@ public class HgConfigAutoConfigurationResourceTest { new HgConfigAutoConfigurationResource(dtoToConfigMapper, repositoryHandler); when(resourceProvider.get()).thenReturn(resource); - dispatcher.getRegistry().addSingletonResource( + dispatcher.addSingletonResource( new HgConfigResource(null, null, null, null, resourceProvider, null)); } @@ -76,9 +73,10 @@ public class HgConfigAutoConfigurationResourceTest { @Test @SubjectAware(username = "readOnly") public void shouldNotSetDefaultConfigAndInstallHgWhenNotAuthorized() throws Exception { - thrown.expectMessage("Subject does not have permission [configuration:write:hg]"); + MockHttpResponse response = put(null); - put(null); + assertEquals("Subject does not have permission [configuration:write:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -95,9 +93,10 @@ public class HgConfigAutoConfigurationResourceTest { @Test @SubjectAware(username = "readOnly") public void shouldNotUpdateConfigAndInstallHgWhenNotAuthorized() throws Exception { - thrown.expectMessage("Subject does not have permission [configuration:write:hg]"); + MockHttpResponse response = put("{\"disabled\":true}"); - put("{\"disabled\":true}"); + assertEquals("Subject does not have permission [configuration:write:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } private MockHttpResponse put(String content) throws URISyntaxException { diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java index 2293d1ddb7..827c69d57f 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java @@ -2,19 +2,17 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; -import org.jboss.resteasy.spi.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.junit.MockitoJUnitRunner; +import sonia.scm.web.ScmTestDispatcher; import javax.inject.Provider; import javax.servlet.http.HttpServletResponse; @@ -35,10 +33,7 @@ public class HgConfigInstallationsResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); @@ -57,7 +52,7 @@ public class HgConfigInstallationsResourceTest { HgConfigInstallationsResource resource = new HgConfigInstallationsResource(mapper); when(resourceProvider.get()).thenReturn(resource); - dispatcher.getRegistry().addSingletonResource( + dispatcher.addSingletonResource( new HgConfigResource(null, null, null, null, null, resourceProvider)); @@ -82,9 +77,10 @@ public class HgConfigInstallationsResourceTest { @Test @SubjectAware(username = "writeOnly") public void shouldNotGetHgInstallationsWhenNotAuthorized() throws Exception { - thrown.expectMessage("Subject does not have permission [configuration:read:hg]"); + MockHttpResponse response = get("hg"); - get("hg"); + assertEquals("Subject does not have permission [configuration:read:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -104,9 +100,10 @@ public class HgConfigInstallationsResourceTest { @Test @SubjectAware(username = "writeOnly") public void shouldNotGetPythonInstallationsWhenNotAuthorized() throws Exception { - thrown.expectMessage("Subject does not have permission [configuration:read:hg]"); + MockHttpResponse response = get("python"); - get("python"); + assertEquals("Subject does not have permission [configuration:read:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } private MockHttpResponse get(String path) throws URISyntaxException { diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java index 29032ac8de..6b77b7a0fc 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java @@ -5,14 +5,11 @@ 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.spi.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; @@ -23,6 +20,7 @@ import sonia.scm.installer.HgPackageReader; import sonia.scm.net.ahc.AdvancedHttpClient; import sonia.scm.repository.HgConfig; import sonia.scm.repository.HgRepositoryHandler; +import sonia.scm.web.ScmTestDispatcher; import javax.inject.Provider; import javax.servlet.http.HttpServletResponse; @@ -49,10 +47,7 @@ public class HgConfigPackageResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = java.net.URI.create("/"); @@ -113,9 +108,10 @@ public class HgConfigPackageResourceTest { @Test @SubjectAware(username = "writeOnly") public void shouldNotGetPackagesWhenNotAuthorized() throws Exception { - thrown.expectMessage("Subject does not have permission [configuration:read:hg]"); + MockHttpResponse response = get(); - get(); + assertEquals("Subject does not have permission [configuration:read:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -158,9 +154,10 @@ public class HgConfigPackageResourceTest { @Test @SubjectAware(username = "readOnly") public void shouldNotInstallPackageWhenNotAuthorized() throws Exception { - thrown.expectMessage("Subject does not have permission [configuration:write:hg]"); + MockHttpResponse response = put("don-t-care"); - put("don-t-care"); + assertEquals("Subject does not have permission [configuration:write:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } private List createPackages() { @@ -191,7 +188,7 @@ public class HgConfigPackageResourceTest { new HgConfigPackageResource(hgPackageReader, advancedHttpClient, repositoryHandler, mapper); when(hgConfigPackageResourceProvider.get()).thenReturn(hgConfigPackageResource); - dispatcher.getRegistry().addSingletonResource( + dispatcher.addSingletonResource( new HgConfigResource(null, null, null, hgConfigPackageResourceProvider, null, null)); } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java index 910f5721e9..f03c894b13 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigResourceTest.java @@ -4,14 +4,11 @@ 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.spi.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; @@ -20,6 +17,7 @@ import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.repository.HgConfig; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.web.HgVndMediaType; +import sonia.scm.web.ScmTestDispatcher; import javax.inject.Provider; import javax.servlet.http.HttpServletResponse; @@ -43,10 +41,7 @@ public class HgConfigResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); @@ -78,7 +73,7 @@ public class HgConfigResourceTest { HgConfigResource gitConfigResource = new HgConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, packagesResource, autoconfigResource, installationsResource); - dispatcher.getRegistry().addSingletonResource(gitConfigResource); + dispatcher.addSingletonResource(gitConfigResource); when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @@ -120,10 +115,11 @@ public class HgConfigResourceTest { @Test @SubjectAware(username = "writeOnly") - public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException { - thrown.expectMessage("Subject does not have permission [configuration:read:hg]"); + public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { + MockHttpResponse response = get(); - get(); + assertEquals("Subject does not have permission [configuration:read:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -135,10 +131,11 @@ public class HgConfigResourceTest { @Test @SubjectAware(username = "readOnly") - public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException { - thrown.expectMessage("Subject does not have permission [configuration:write:hg]"); + public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { + MockHttpResponse response = put(); - put(); + assertEquals("Subject does not have permission [configuration:write:hg]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } private MockHttpResponse get() throws URISyntaxException { 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 index 6a854471dd..225c838a6c 100644 --- 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 @@ -4,14 +4,11 @@ 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.spi.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; @@ -19,6 +16,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.repository.SvnConfig; import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.SvnVndMediaType; import javax.servlet.http.HttpServletResponse; @@ -42,10 +40,7 @@ public class SvnConfigResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); @@ -66,7 +61,7 @@ public class SvnConfigResourceTest { SvnConfig gitConfig = createConfiguration(); when(repositoryHandler.getConfig()).thenReturn(gitConfig); SvnConfigResource gitConfigResource = new SvnConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); - dispatcher.getRegistry().addSingletonResource(gitConfigResource); + dispatcher.addSingletonResource(gitConfigResource); when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } @@ -108,10 +103,11 @@ public class SvnConfigResourceTest { @Test @SubjectAware(username = "writeOnly") - public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException { - thrown.expectMessage("Subject does not have permission [configuration:read:svn]"); + public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { + MockHttpResponse response = get(); - get(); + assertEquals("Subject does not have permission [configuration:read:svn]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -123,10 +119,11 @@ public class SvnConfigResourceTest { @Test @SubjectAware(username = "readOnly") - public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException { - thrown.expectMessage("Subject does not have permission [configuration:write:svn]"); + public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { + MockHttpResponse response = put(); - put(); + assertEquals("Subject does not have permission [configuration:write:svn]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } private MockHttpResponse get() throws URISyntaxException { diff --git a/scm-test/pom.xml b/scm-test/pom.xml index bddbcf2c85..d36b8c55f8 100644 --- a/scm-test/pom.xml +++ b/scm-test/pom.xml @@ -42,6 +42,20 @@ ${mockito.version} + + org.jboss.resteasy + resteasy-core-spi + + + org.jboss.resteasy + resteasy-core + + + org.jboss.resteasy + resteasy-jackson2-provider + ${resteasy.version} + + org.slf4j slf4j-simple diff --git a/scm-test/src/main/java/sonia/scm/web/ScmTestDispatcher.java b/scm-test/src/main/java/sonia/scm/web/ScmTestDispatcher.java new file mode 100644 index 0000000000..f8b3040f73 --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/web/ScmTestDispatcher.java @@ -0,0 +1,109 @@ +package sonia.scm.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.shiro.authz.AuthorizationException; +import org.apache.shiro.authz.UnauthorizedException; +import org.jboss.resteasy.mock.MockDispatcherFactory; +import org.jboss.resteasy.spi.Dispatcher; +import org.jboss.resteasy.spi.HttpRequest; +import org.jboss.resteasy.spi.HttpResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sonia.scm.AlreadyExistsException; +import sonia.scm.BadRequestException; +import sonia.scm.ConcurrentModificationException; +import sonia.scm.NotFoundException; + +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import java.util.HashMap; +import java.util.Map; + +public class ScmTestDispatcher { + + private static final Logger LOG = LoggerFactory.getLogger(ScmTestDispatcher.class); + + private final Dispatcher dispatcher; + private final EnhanceableExceptionMapper exceptionMapper; + + public ScmTestDispatcher() { + dispatcher = MockDispatcherFactory.createDispatcher(); + exceptionMapper = new EnhanceableExceptionMapper(); + dispatcher.getProviderFactory().register(exceptionMapper); + dispatcher.getProviderFactory().registerProviderInstance(new JacksonProducer()); + } + + public void addSingletonResource(Object resource) { + dispatcher.getRegistry().addSingletonResource(resource); + } + + public void invoke(HttpRequest in, HttpResponse response) { + dispatcher.invoke(in, response); + } + + public void registerException(Class exceptionClass, Status status) { + exceptionMapper.registerException(exceptionClass, status); + } + + public void putDefaultContextObject(Class clazz, T object) { + dispatcher.getDefaultContextObjects().put(clazz, object); + } + + private static class EnhanceableExceptionMapper implements ExceptionMapper { + + private final Map, Integer> statusCodes = new HashMap<>(); + + public EnhanceableExceptionMapper() { + registerException(NotFoundException.class, Status.NOT_FOUND); + registerException(AlreadyExistsException.class, Status.CONFLICT); + registerException(ConcurrentModificationException.class, Status.CONFLICT); + registerException(UnauthorizedException.class, Status.FORBIDDEN); + registerException(AuthorizationException.class, Status.FORBIDDEN); + registerException(BadRequestException.class, Status.BAD_REQUEST); + } + + private void registerException(Class exceptionClass, Status status) { + statusCodes.put(exceptionClass, status.getStatusCode()); + } + + @Override + public Response toResponse(Exception e) { + return Response.status(getStatus(e)).entity(e.getMessage()).build(); + } + + private Integer getStatus(Exception ex) { + return statusCodes + .entrySet() + .stream() + .filter(e -> e.getKey().isAssignableFrom(ex.getClass())) + .map(Map.Entry::getValue) + .findAny() + .orElse(handleUnknownException(ex)); + } + + private Integer handleUnknownException(Exception ex) { + LOG.info("got unknown exception in rest api test", ex); + return 500; + } + } + + @Provider + @Produces("application/*+json") + public static class JacksonProducer implements ContextResolver { + public JacksonProducer() { + this.json + = new ObjectMapper().findAndRegisterModules(); + } + + @Override + public ObjectMapper getContext(Class objectType) { + return json; + } + + private final ObjectMapper json; + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/api/rest/AuthorizationExceptionMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/rest/AuthorizationExceptionMapperTest.java new file mode 100644 index 0000000000..f546a7cf34 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/api/rest/AuthorizationExceptionMapperTest.java @@ -0,0 +1,5 @@ +package sonia.scm.api.rest; + +class AuthorizationExceptionMapperTest { +// TODO verify differentiation between normal user and anonymous +} diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java index c5756fadd6..e96301ad2a 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java @@ -2,11 +2,8 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; -import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -19,18 +16,17 @@ import sonia.scm.security.AccessTokenBuilder; import sonia.scm.security.AccessTokenBuilderFactory; import sonia.scm.security.AccessTokenCookieIssuer; import sonia.scm.security.DefaultAccessTokenCookieIssuer; +import sonia.scm.web.ScmTestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.MediaType; import java.io.UnsupportedEncodingException; -import java.net.URI; import java.net.URISyntaxException; import java.util.Date; import java.util.Optional; import static java.net.URI.create; -import static java.util.Optional.empty; import static java.util.Optional.of; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; @@ -47,7 +43,7 @@ public class AuthenticationResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock private AccessTokenBuilderFactory accessTokenBuilderFactory; @@ -116,7 +112,7 @@ public class AuthenticationResourceTest { @Before public void prepareEnvironment() { authenticationResource = new AuthenticationResource(accessTokenBuilderFactory, cookieIssuer); - dispatcher.getRegistry().addSingletonResource(authenticationResource); + dispatcher.addSingletonResource(authenticationResource); AccessToken accessToken = mock(AccessToken.class); when(accessToken.getExpiration()).thenReturn(new Date(Long.MAX_VALUE)); @@ -125,9 +121,9 @@ public class AuthenticationResourceTest { when(accessTokenBuilderFactory.create()).thenReturn(accessTokenBuilder); HttpServletRequest servletRequest = mock(HttpServletRequest.class); - dispatcher.getDefaultContextObjects().put(HttpServletRequest.class, servletRequest); + dispatcher.putDefaultContextObject(HttpServletRequest.class, servletRequest); HttpServletResponse servletResponse = mock(HttpServletResponse.class); - dispatcher.getDefaultContextObjects().put(HttpServletResponse.class, servletResponse); + dispatcher.putDefaultContextObject(HttpServletResponse.class, servletResponse); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AutoCompleteResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AutoCompleteResourceTest.java index f8b4236b41..7356feafe1 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AutoCompleteResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AutoCompleteResourceTest.java @@ -5,7 +5,6 @@ import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import org.apache.shiro.util.ThreadContext; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -23,6 +22,7 @@ import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.user.DefaultUserDisplayManager; import sonia.scm.user.User; import sonia.scm.user.xml.XmlUserDAO; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import sonia.scm.xml.XmlDatabase; @@ -39,7 +39,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @SubjectAware(configuration = "classpath:sonia/scm/shiro-002.ini") @RunWith(MockitoJUnitRunner.Silent.class) @@ -50,7 +49,8 @@ public class AutoCompleteResourceTest { public static final String URL = "/" + AutoCompleteResource.PATH; private final Integer defaultLimit = DisplayManager.DEFAULT_LIMIT; - private Dispatcher dispatcher; + + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private XmlUserDAO userDao; private XmlGroupDAO groupDao; @@ -74,7 +74,7 @@ public class AutoCompleteResourceTest { DefaultUserDisplayManager userManager = new DefaultUserDisplayManager(this.userDao); DefaultGroupDisplayManager groupManager = new DefaultGroupDisplayManager(groupDao); AutoCompleteResource autoCompleteResource = new AutoCompleteResource(mapper, userManager, groupManager); - dispatcher = createDispatcher(autoCompleteResource); + dispatcher.addSingletonResource(autoCompleteResource); } @After diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AvailablePluginResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AvailablePluginResourceTest.java index 99190d942d..fd8b8b9fe9 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AvailablePluginResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AvailablePluginResourceTest.java @@ -1,14 +1,11 @@ package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; -import org.apache.shiro.ShiroException; +import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ThreadContext; -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; -import org.jboss.resteasy.spi.UnhandledException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -24,6 +21,7 @@ import sonia.scm.plugin.InstalledPluginDescriptor; import sonia.scm.plugin.PluginCondition; import sonia.scm.plugin.PluginInformation; import sonia.scm.plugin.PluginManager; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.inject.Provider; @@ -34,7 +32,7 @@ import java.util.Collections; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; @@ -46,7 +44,7 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class AvailablePluginResourceTest { - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock Provider availablePluginResourceProvider; @@ -71,10 +69,9 @@ class AvailablePluginResourceTest { @BeforeEach void prepareEnvironment() { - dispatcher = MockDispatcherFactory.createDispatcher(); pluginRootResource = new PluginRootResource(null, availablePluginResourceProvider, null); when(availablePluginResourceProvider.get()).thenReturn(availablePluginResource); - dispatcher.getRegistry().addSingletonResource(pluginRootResource); + dispatcher.addSingletonResource(pluginRootResource); } @Nested @@ -195,20 +192,23 @@ class AvailablePluginResourceTest { @BeforeEach void bindSubject() { ThreadContext.bind(subject); - doThrow(new ShiroException()).when(subject).checkPermission(any(String.class)); + doThrow(new UnauthorizedException()).when(subject).checkPermission(any(String.class)); } @AfterEach public void unbindSubject() { ThreadContext.unbindSubject(); } + @Test void shouldNotGetAvailablePluginsIfMissingPermission() throws URISyntaxException { MockHttpRequest request = MockHttpRequest.get("/v2/plugins/available"); request.accept(VndMediaType.PLUGIN_COLLECTION); MockHttpResponse response = new MockHttpResponse(); - assertThrows(UnhandledException.class, () -> dispatcher.invoke(request, response)); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); verify(subject).checkPermission(any(String.class)); } @@ -218,7 +218,9 @@ class AvailablePluginResourceTest { request.accept(VndMediaType.PLUGIN); MockHttpResponse response = new MockHttpResponse(); - assertThrows(UnhandledException.class, () -> dispatcher.invoke(request, response)); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); verify(subject).checkPermission(any(String.class)); } @@ -228,7 +230,9 @@ class AvailablePluginResourceTest { request.accept(VndMediaType.PLUGIN); MockHttpResponse response = new MockHttpResponse(); - assertThrows(UnhandledException.class, () -> dispatcher.invoke(request, response)); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); verify(subject).checkPermission(any(String.class)); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java index 45a2d1613c..43f3d9f74e 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/BranchRootResourceTest.java @@ -6,10 +6,10 @@ 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.assertj.core.api.Assertions; import org.assertj.core.util.Lists; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; -import org.jboss.resteasy.spi.Dispatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -29,6 +29,7 @@ import sonia.scm.repository.api.BranchesCommandBuilder; import sonia.scm.repository.api.LogCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.ws.rs.core.MediaType; @@ -39,8 +40,13 @@ import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.Silent.class) @Slf4j @@ -49,7 +55,8 @@ public class BranchRootResourceTest extends RepositoryTestBase { public static final String BRANCH_PATH = "space/repo/branches/master"; public static final String BRANCH_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + BRANCH_PATH; public static final String REVISION = "revision"; - private Dispatcher dispatcher; + + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); @@ -96,7 +103,7 @@ public class BranchRootResourceTest extends RepositoryTestBase { BranchCollectionToDtoMapper branchCollectionToDtoMapper = new BranchCollectionToDtoMapper(branchToDtoMapper, resourceLinks); branchRootResource = new BranchRootResource(serviceFactory, branchToDtoMapper, branchCollectionToDtoMapper, changesetCollectionToDtoMapper, resourceLinks); super.branchRootResource = Providers.of(branchRootResource); - dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service); when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); @@ -125,7 +132,7 @@ public class BranchRootResourceTest extends RepositoryTestBase { assertEquals(404, response.getStatus()); MediaType contentType = (MediaType) response.getOutputHeaders().getFirst("Content-Type"); - assertEquals("application/vnd.scmm-error+json;v=2", contentType.toString()); + Assertions.assertThat(response.getContentAsString()).contains("branch", "master", "space/repo"); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java index 601a4a4652..5e890e36e6 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetRootResourceTest.java @@ -8,7 +8,6 @@ import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -26,6 +25,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.api.LogCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import java.net.URI; @@ -48,7 +48,7 @@ public class ChangesetRootResourceTest extends RepositoryTestBase { public static final String CHANGESET_PATH = "space/repo/changesets/"; public static final String CHANGESET_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + CHANGESET_PATH; - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); @@ -79,7 +79,7 @@ public class ChangesetRootResourceTest extends RepositoryTestBase { changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks); changesetRootResource = new ChangesetRootResource(serviceFactory, changesetCollectionToDtoMapper, changesetToChangesetDtoMapper); super.changesetRootResource = Providers.of(changesetRootResource); - dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java index 74bb0ab38a..68a743dab3 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java @@ -4,18 +4,16 @@ import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; import org.apache.shiro.util.ThreadContext; -import org.jboss.resteasy.spi.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.mockito.InjectMocks; import org.mockito.Mock; import sonia.scm.config.ScmConfiguration; import sonia.scm.repository.NamespaceStrategyValidator; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -41,10 +39,7 @@ public class ConfigResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - @Rule - public ExpectedException thrown = ExpectedException.none(); - - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); @SuppressWarnings("unused") // Is injected @@ -71,7 +66,7 @@ public class ConfigResourceTest { ConfigResource configResource = new ConfigResource(dtoToConfigMapper, configToDtoMapper, createConfiguration(), namespaceStrategyValidator); - dispatcher.getRegistry().addSingletonResource(configResource); + dispatcher.addSingletonResource(configResource); } @Test @@ -88,13 +83,14 @@ public class ConfigResourceTest { @Test @SubjectAware(username = "writeOnly") - public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException { + public void shouldNotGetConfigWhenNotAuthorized() throws URISyntaxException, UnsupportedEncodingException { MockHttpRequest request = MockHttpRequest.get("/" + ConfigResource.CONFIG_PATH_V2); MockHttpResponse response = new MockHttpResponse(); - thrown.expectMessage("Subject does not have permission [configuration:read:global]"); - dispatcher.invoke(request, response); + + assertEquals("Subject does not have permission [configuration:read:global]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -120,9 +116,10 @@ public class ConfigResourceTest { MockHttpRequest request = post("sonia/scm/api/v2/config-test-update.json"); MockHttpResponse response = new MockHttpResponse(); - thrown.expectMessage("Subject does not have permission [configuration:write:global]"); - dispatcher.invoke(request, response); + + assertEquals("Subject does not have permission [configuration:write:global]", response.getContentAsString()); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java index c3d4b2fffa..fd41150aa8 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DiffResourceTest.java @@ -7,8 +7,6 @@ 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.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -18,16 +16,17 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.NotFoundException; -import sonia.scm.api.rest.AuthorizationExceptionMapper; -import sonia.scm.api.v2.NotFoundExceptionMapper; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffFormat; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.util.CRLFInjectionException; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; +import javax.ws.rs.core.Response; import java.net.URISyntaxException; import java.util.Arrays; @@ -46,7 +45,8 @@ public class DiffResourceTest extends RepositoryTestBase { public static final String DIFF_PATH = "space/repo/diff/"; public static final String DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + DIFF_PATH; - private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock private RepositoryServiceFactory serviceFactory; @@ -68,14 +68,12 @@ public class DiffResourceTest extends RepositoryTestBase { public void prepareEnvironment() { diffRootResource = new DiffRootResource(serviceFactory); super.diffRootResource = Providers.of(diffRootResource); - dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service); when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl(); - dispatcher.getProviderFactory().register(new NotFoundExceptionMapper(mapper)); - dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class); - dispatcher.getProviderFactory().registerProvider(CRLFInjectionExceptionMapper.class); + dispatcher.registerException(CRLFInjectionException.class, Response.Status.BAD_REQUEST); when(service.getDiffCommand()).thenReturn(diffCommandBuilder); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DispatcherMock.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DispatcherMock.java deleted file mode 100644 index 40b2ac54b7..0000000000 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DispatcherMock.java +++ /dev/null @@ -1,24 +0,0 @@ -package sonia.scm.api.v2.resources; - -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; -import sonia.scm.api.rest.AlreadyExistsExceptionMapper; -import sonia.scm.api.rest.AuthorizationExceptionMapper; -import sonia.scm.api.rest.BadRequestExceptionMapper; -import sonia.scm.api.rest.ConcurrentModificationExceptionMapper; -import sonia.scm.api.v2.NotFoundExceptionMapper; - -public class DispatcherMock { - public static Dispatcher createDispatcher(Object resource) { - Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); - dispatcher.getRegistry().addSingletonResource(resource); - ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl(); - dispatcher.getProviderFactory().register(new NotFoundExceptionMapper(mapper)); - dispatcher.getProviderFactory().register(new AlreadyExistsExceptionMapper(mapper)); - dispatcher.getProviderFactory().register(new ConcurrentModificationExceptionMapper(mapper)); - dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class); - dispatcher.getProviderFactory().register(new InternalRepositoryExceptionMapper(mapper)); - dispatcher.getProviderFactory().register(new BadRequestExceptionMapper(mapper)); - return dispatcher; - } -} diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/FileHistoryResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/FileHistoryResourceTest.java index b5b903508a..907729d161 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/FileHistoryResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/FileHistoryResourceTest.java @@ -7,7 +7,6 @@ import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -28,6 +27,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.api.LogCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import java.net.URI; @@ -70,7 +70,7 @@ public class FileHistoryResourceTest extends RepositoryTestBase { private FileHistoryRootResource fileHistoryRootResource; - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final Subject subject = mock(Subject.class); private final ThreadState subjectThreadState = new SubjectThreadState(subject); @@ -80,7 +80,7 @@ public class FileHistoryResourceTest extends RepositoryTestBase { fileHistoryCollectionToDtoMapper = new FileHistoryCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks); fileHistoryRootResource = new FileHistoryRootResource(serviceFactory, fileHistoryCollectionToDtoMapper); super.fileHistoryRootResource = Providers.of(fileHistoryRootResource); - dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service); when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java index bb024eb67c..97088f9d6f 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/GroupRootResourceTest.java @@ -4,7 +4,6 @@ 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.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -15,12 +14,11 @@ import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import sonia.scm.PageResult; -import sonia.scm.api.rest.JSONContextResolver; -import sonia.scm.api.rest.ObjectMapperProvider; import sonia.scm.group.Group; import sonia.scm.group.GroupManager; import sonia.scm.security.PermissionAssigner; import sonia.scm.security.PermissionDescriptor; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -43,7 +41,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @SubjectAware( username = "trillian", @@ -55,7 +52,7 @@ public class GroupRootResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("/")); @@ -91,8 +88,7 @@ public class GroupRootResourceTest { GroupResource groupResource = new GroupResource(groupManager, groupToDtoMapper, dtoToGroupMapper, groupPermissionResource); GroupRootResource groupRootResource = new GroupRootResource(Providers.of(groupCollectionResource), Providers.of(groupResource)); - dispatcher = createDispatcher(groupRootResource); - dispatcher.getProviderFactory().registerProviderInstance(new JSONContextResolver(new ObjectMapperProvider().get())); + dispatcher.addSingletonResource(groupRootResource); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java index de0eaeb992..481960e8c7 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/IncomingRootResourceTest.java @@ -8,7 +8,6 @@ import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -28,8 +27,11 @@ import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.LogCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.util.CRLFInjectionException; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; +import javax.ws.rs.core.Response; import java.net.URI; import java.net.URISyntaxException; import java.time.Instant; @@ -53,7 +55,7 @@ public class IncomingRootResourceTest extends RepositoryTestBase { public static final String INCOMING_CHANGESETS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH; public static final String INCOMING_DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH; - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); @@ -88,13 +90,13 @@ public class IncomingRootResourceTest extends RepositoryTestBase { incomingChangesetCollectionToDtoMapper = new IncomingChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks); incomingRootResource = new IncomingRootResource(serviceFactory, incomingChangesetCollectionToDtoMapper); super.incomingRootResource = Providers.of(incomingRootResource); - dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); when(repositoryService.getLogCommand()).thenReturn(logCommandBuilder); when(repositoryService.getDiffCommand()).thenReturn(diffCommandBuilder); - dispatcher.getProviderFactory().registerProvider(CRLFInjectionExceptionMapper.class); + dispatcher.registerException(CRLFInjectionException.class, Response.Status.BAD_REQUEST); subjectThreadState.bind(); ThreadContext.bind(subject); when(subject.isPermitted(any(String.class))).thenReturn(true); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/InstalledPluginResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/InstalledPluginResourceTest.java index 8c9ed5ef2a..5319725c9d 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/InstalledPluginResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/InstalledPluginResourceTest.java @@ -1,13 +1,11 @@ package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; +import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ThreadContext; -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; -import org.jboss.resteasy.spi.UnhandledException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -17,9 +15,9 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import sonia.scm.plugin.InstalledPlugin; -import sonia.scm.plugin.InstalledPluginDescriptor; import sonia.scm.plugin.PluginInformation; import sonia.scm.plugin.PluginManager; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.inject.Provider; @@ -31,15 +29,17 @@ import java.util.Optional; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static sonia.scm.plugin.PluginTestHelper.createInstalled; @ExtendWith(MockitoExtension.class) class InstalledPluginResourceTest { - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock Provider installedPluginResourceProvider; @@ -65,10 +65,9 @@ class InstalledPluginResourceTest { @BeforeEach void prepareEnvironment() { - dispatcher = MockDispatcherFactory.createDispatcher(); pluginRootResource = new PluginRootResource(installedPluginResourceProvider, null, null); when(installedPluginResourceProvider.get()).thenReturn(installedPluginResource); - dispatcher.getRegistry().addSingletonResource(pluginRootResource); + dispatcher.addSingletonResource(pluginRootResource); } @Nested @@ -77,7 +76,6 @@ class InstalledPluginResourceTest { @BeforeEach void bindSubject() { ThreadContext.bind(subject); - when(subject.isPermitted(any(String.class))).thenReturn(true); } @AfterEach @@ -129,7 +127,13 @@ class InstalledPluginResourceTest { class WithoutAuthorization { @BeforeEach - void unbindSubject() { + void bindSubject() { + ThreadContext.bind(subject); + doThrow(new UnauthorizedException()).when(subject).checkPermission(any(String.class)); + } + + @AfterEach + public void unbindSubject() { ThreadContext.unbindSubject(); } @@ -139,7 +143,9 @@ class InstalledPluginResourceTest { request.accept(VndMediaType.PLUGIN_COLLECTION); MockHttpResponse response = new MockHttpResponse(); - assertThrows(UnhandledException.class, () -> dispatcher.invoke(request, response)); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } @Test @@ -148,7 +154,9 @@ class InstalledPluginResourceTest { request.accept(VndMediaType.PLUGIN); MockHttpResponse response = new MockHttpResponse(); - assertThrows(UnhandledException.class, () -> dispatcher.invoke(request, response)); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java index 7aeabe6bec..1c876755a6 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java @@ -7,7 +7,6 @@ import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.credential.PasswordService; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -21,6 +20,7 @@ import sonia.scm.group.GroupCollector; import sonia.scm.user.InvalidPasswordException; import sonia.scm.user.User; import sonia.scm.user.UserManager; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -37,7 +37,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @SubjectAware( username = "trillian", @@ -49,9 +48,10 @@ public class MeResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("/")); + @Mock private ScmPathInfo uriInfo; @Mock @@ -85,7 +85,7 @@ public class MeResourceTest { MeResource meResource = new MeResource(meDtoFactory, userManager, passwordService); when(uriInfo.getApiRestUri()).thenReturn(URI.create("/")); when(scmPathInfoStore.get()).thenReturn(uriInfo); - dispatcher = createDispatcher(meResource); + dispatcher.addSingletonResource(meResource); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ModificationsResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ModificationsResourceTest.java index 8e84f9d1bb..6806dd248e 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ModificationsResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ModificationsResourceTest.java @@ -7,7 +7,6 @@ import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -24,6 +23,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.api.ModificationsCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import java.net.URI; @@ -45,7 +45,7 @@ public class ModificationsResourceTest extends RepositoryTestBase { public static final String MODIFICATIONS_PATH = "space/repo/modifications/"; public static final String MODIFICATIONS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + MODIFICATIONS_PATH; - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); @@ -73,7 +73,7 @@ public class ModificationsResourceTest extends RepositoryTestBase { public void prepareEnvironment() { modificationsRootResource = new ModificationsRootResource(serviceFactory, modificationsToDtoMapper); super.modificationsRootResource = Providers.of(modificationsRootResource); - dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java index 3613069d63..be5374472f 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java @@ -4,8 +4,6 @@ import com.google.inject.util.Providers; import org.apache.shiro.ShiroException; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ThreadContext; -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.jupiter.api.AfterEach; @@ -22,10 +20,10 @@ import sonia.scm.plugin.InstalledPlugin; import sonia.scm.plugin.InstalledPluginDescriptor; import sonia.scm.plugin.PluginInformation; import sonia.scm.plugin.PluginManager; +import sonia.scm.web.ScmTestDispatcher; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; @@ -42,7 +40,7 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class PendingPluginResourceTest { - Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); ResourceLinks resourceLinks = ResourceLinksMock.createMock(create("/")); @@ -61,10 +59,9 @@ class PendingPluginResourceTest { @BeforeEach void prepareEnvironment() { - dispatcher = MockDispatcherFactory.createDispatcher(); - dispatcher.getProviderFactory().register(new PermissionExceptionMapper()); + dispatcher.registerException(ShiroException.class, Response.Status.UNAUTHORIZED); PluginRootResource pluginRootResource = new PluginRootResource(null, null, Providers.of(pendingPluginResource)); - dispatcher.getRegistry().addSingletonResource(pluginRootResource); + dispatcher.addSingletonResource(pluginRootResource); } @BeforeEach @@ -207,14 +204,6 @@ class PendingPluginResourceTest { } } - static class PermissionExceptionMapper implements ExceptionMapper { - - @Override - public Response toResponse(ShiroException exception) { - return Response.status(401).entity(exception.getMessage()).build(); - } - } - private AvailablePlugin createAvailablePlugin(String name) { PluginInformation pluginInformation = new PluginInformation(); pluginInformation.setName(name); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java index a2e63dd50e..8ad4522b4d 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java @@ -13,7 +13,6 @@ import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.jboss.resteasy.spi.HttpRequest; @@ -30,6 +29,7 @@ import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryPermission; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.ws.rs.HttpMethod; @@ -58,7 +58,6 @@ import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; import static sonia.scm.api.v2.resources.RepositoryPermissionDto.GROUP_PREFIX; @Slf4j @@ -105,7 +104,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { .content(PERMISSION_TEST_PAYLOAD) .path(PATH_OF_ONE_PERMISSION); - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock private RepositoryManager repositoryManager; @@ -133,7 +132,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { repositoryPermissionCollectionToDtoMapper = new RepositoryPermissionCollectionToDtoMapper(permissionToPermissionDtoMapper, resourceLinks); repositoryPermissionRootResource = new RepositoryPermissionRootResource(permissionDtoToPermissionMapper, permissionToPermissionDtoMapper, repositoryPermissionCollectionToDtoMapper, resourceLinks, repositoryManager); super.permissionRootResource = Providers.of(repositoryPermissionRootResource); - dispatcher = createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); subjectThreadState.bind(); ThreadContext.bind(subject); } @@ -180,19 +179,6 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { requestPUTPermission.expectedResponseStatus(403)); } - @TestFactory - @DisplayName("test endpoints on missing permissions and is _anonymous") - Stream missedPermissionAnonymousUnauthorizedTestFactory() { - when(subject.getPrincipal()).thenReturn("_anonymous"); - doThrow(AuthorizationException.class).when(repositoryManager).get(any(NamespaceAndName.class)); - return createDynamicTestsToAssertResponses( - requestGETPermission.expectedResponseStatus(401), - requestPOSTPermission.expectedResponseStatus(401), - requestGETAllPermissions.expectedResponseStatus(401), - requestDELETEPermission.expectedResponseStatus(401), - requestPUTPermission.expectedResponseStatus(401)); - } - @Test public void userWithPermissionWritePermissionShouldGetAllPermissionsWithCreateAndUpdateLinks() throws URISyntaxException { createUserWithRepositoryAndPermissions(TEST_PERMISSIONS, PERMISSION_WRITE); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRoleRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRoleRootResourceTest.java index d60a32f5dc..e458af6a11 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRoleRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRoleRootResourceTest.java @@ -3,7 +3,6 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.inject.util.Providers; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -16,10 +15,9 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.PageResult; -import sonia.scm.api.rest.JSONContextResolver; -import sonia.scm.api.rest.ObjectMapperProvider; import sonia.scm.repository.RepositoryRole; import sonia.scm.repository.RepositoryRoleManager; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -36,7 +34,6 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @SubjectAware( username = "trillian", @@ -66,7 +63,7 @@ public class RepositoryRoleRootResourceTest { private RepositoryRoleCollectionToDtoMapper collectionToDtoMapper; - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Captor private ArgumentCaptor modifyCaptor; @@ -87,8 +84,7 @@ public class RepositoryRoleRootResourceTest { when(repositoryRoleManager.create(createCaptor.capture())).thenAnswer(invocation -> invocation.getArguments()[0]); doNothing().when(repositoryRoleManager).delete(deleteCaptor.capture()); - dispatcher = createDispatcher(rootResource); - dispatcher.getProviderFactory().registerProviderInstance(new JSONContextResolver(new ObjectMapperProvider().get())); + dispatcher.addSingletonResource(rootResource); when(repositoryRoleManager.get(CUSTOM_ROLE)).thenReturn(CUSTOM_REPOSITORY_ROLE); when(repositoryRoleManager.get(SYSTEM_ROLE)).thenReturn(SYSTEM_REPOSITORY_ROLE); 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 fcd34334b2..206f7713a3 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 @@ -6,7 +6,6 @@ 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.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -23,6 +22,7 @@ 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.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -47,12 +47,10 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @SubjectAware( username = "trillian", @@ -63,7 +61,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { private static final String REALM = "AdminRealm"; - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Rule public ShiroRule shiro = new ShiroRule(); @@ -98,7 +96,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { super.manager = repositoryManager; RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks); super.repositoryCollectionResource = Providers.of(new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks)); - dispatcher = createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(scmPathInfoStore.get()).thenReturn(uriInfo); when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y")); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java index 17ea3248c2..3dd30e21c0 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryTypeRootResourceTest.java @@ -3,8 +3,6 @@ package sonia.scm.api.v2.resources; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.inject.util.Providers; -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -15,6 +13,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryType; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import java.net.URI; @@ -32,7 +31,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.Silent.class) public class RepositoryTypeRootResourceTest { - private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock private RepositoryManager repositoryManager; @@ -56,7 +55,7 @@ public class RepositoryTypeRootResourceTest { RepositoryTypeCollectionResource collectionResource = new RepositoryTypeCollectionResource(repositoryManager, collectionMapper); RepositoryTypeResource resource = new RepositoryTypeResource(repositoryManager, mapper); RepositoryTypeRootResource rootResource = new RepositoryTypeRootResource(Providers.of(collectionResource), Providers.of(resource)); - dispatcher.getRegistry().addSingletonResource(rootResource); + dispatcher.addSingletonResource(rootResource); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java index a25aabaca1..4dd694c092 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/SourceRootResourceTest.java @@ -1,7 +1,6 @@ package sonia.scm.api.v2.resources; import com.google.inject.util.Providers; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -18,6 +17,7 @@ import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.api.BrowseCommandBuilder; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.web.ScmTestDispatcher; import java.io.IOException; import java.net.URI; @@ -25,13 +25,12 @@ import java.net.URISyntaxException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @RunWith(MockitoJUnitRunner.Silent.class) public class SourceRootResourceTest extends RepositoryTestBase { - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); @@ -58,7 +57,7 @@ public class SourceRootResourceTest extends RepositoryTestBase { SourceRootResource sourceRootResource = new SourceRootResource(serviceFactory, browserResultToFileObjectDtoMapper); super.sourceRootResource = Providers.of(sourceRootResource); - dispatcher = createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java index e97f6c726f..29616db703 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/TagRootResourceTest.java @@ -7,7 +7,6 @@ import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.util.ThreadState; import org.assertj.core.util.Lists; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.After; @@ -17,8 +16,6 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.api.rest.AuthorizationExceptionMapper; -import sonia.scm.api.v2.NotFoundExceptionMapper; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.repository.Tag; @@ -26,6 +23,7 @@ import sonia.scm.repository.Tags; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.api.TagsCommandBuilder; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import java.net.URI; @@ -36,7 +34,6 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @Slf4j @RunWith(MockitoJUnitRunner.Silent.class) @@ -44,7 +41,8 @@ public class TagRootResourceTest extends RepositoryTestBase { public static final String TAG_PATH = "space/repo/tags/"; public static final String TAG_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + TAG_PATH; - private Dispatcher dispatcher ; + + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final URI baseUri = URI.create("/"); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri); @@ -74,12 +72,10 @@ public class TagRootResourceTest extends RepositoryTestBase { tagCollectionToDtoMapper = new TagCollectionToDtoMapper(resourceLinks, tagToTagDtoMapper); tagRootResource = new TagRootResource(serviceFactory, tagCollectionToDtoMapper, tagToTagDtoMapper); super.tagRootResource = Providers.of(tagRootResource); - dispatcher = createDispatcher(getRepositoryRootResource()); + dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); - dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class); - dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class); when(repositoryService.getTagsCommand()).thenReturn(tagsCommandBuilder); subjectThreadState.bind(); ThreadContext.bind(subject); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UIRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UIRootResourceTest.java index 0391e43c81..da0c862168 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UIRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UIRootResourceTest.java @@ -3,8 +3,6 @@ package sonia.scm.api.v2.resources; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.inject.util.Providers; -import org.jboss.resteasy.spi.Dispatcher; -import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -12,7 +10,12 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.plugin.*; +import sonia.scm.plugin.InstalledPlugin; +import sonia.scm.plugin.InstalledPluginDescriptor; +import sonia.scm.plugin.PluginInformation; +import sonia.scm.plugin.PluginLoader; +import sonia.scm.plugin.PluginResources; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletRequest; @@ -24,14 +27,17 @@ import java.util.HashSet; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static javax.servlet.http.HttpServletResponse.SC_OK; import static org.hamcrest.Matchers.equalToIgnoringCase; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.Silent.class) public class UIRootResourceTest { - private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); @Mock private PluginLoader pluginLoader; @@ -50,7 +56,7 @@ public class UIRootResourceTest { UIPluginResource pluginResource = new UIPluginResource(pluginLoader, collectionMapper, mapper); UIRootResource rootResource = new UIRootResource(Providers.of(pluginResource)); - dispatcher.getRegistry().addSingletonResource(rootResource); + dispatcher.addSingletonResource(rootResource); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java index e055bbf3b5..6426007556 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserRootResourceTest.java @@ -5,7 +5,6 @@ import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; import com.google.inject.util.Providers; import org.apache.shiro.authc.credential.PasswordService; -import org.jboss.resteasy.spi.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Before; @@ -23,6 +22,7 @@ import sonia.scm.security.PermissionDescriptor; import sonia.scm.user.ChangePasswordNotAllowedException; import sonia.scm.user.User; import sonia.scm.user.UserManager; +import sonia.scm.web.ScmTestDispatcher; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -45,7 +45,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; @SubjectAware( username = "trillian", @@ -57,7 +56,7 @@ public class UserRootResourceTest { @Rule public ShiroRule shiro = new ShiroRule(); - private Dispatcher dispatcher; + private ScmTestDispatcher dispatcher = new ScmTestDispatcher(); private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("/")); @@ -99,7 +98,7 @@ public class UserRootResourceTest { UserRootResource userRootResource = new UserRootResource(Providers.of(userCollectionResource), Providers.of(userResource)); - dispatcher = createDispatcher(userRootResource); + dispatcher.addSingletonResource(userRootResource); } @Test