From 83d6ab8e9cb49d40801abf023b63bce1c9aa7e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 25 Jun 2018 11:52:36 +0200 Subject: [PATCH] Backed out changeset 5d23ff274a2f --- pom.xml | 355 +++++++------- scm-clients/scm-client-impl/pom.xml | 4 +- scm-core/pom.xml | 6 +- .../scm/security/DefaultCipherHandler.java | 7 +- .../main/java/sonia/scm/web/HgCGIServlet.java | 34 +- scm-webapp/pom.xml | 436 ++++++++++-------- .../main/java/sonia/scm/ScmServletModule.java | 209 +++++++-- .../scm/api/rest/TemplateEngineViewable.java | 64 ++- .../scm/api/rest/UriExtensionsConfig.java | 110 +++-- .../resources/AbstractPermissionResource.java | 8 +- .../resources/ChangePasswordResource.java | 2 +- .../rest/resources/ConfigurationResource.java | 4 +- .../scm/api/rest/resources/GroupResource.java | 8 +- .../api/rest/resources/PluginResource.java | 16 +- .../resources/RepositoryImportResource.java | 27 +- .../rest/resources/RepositoryResource.java | 22 +- .../resources/RepositoryRootResource.java | 21 +- .../api/rest/resources/SearchResource.java | 4 +- .../scm/api/rest/resources/UserResource.java | 8 +- .../java/sonia/scm/debug/DebugResource.java | 4 +- .../scm/net/ahc/JsonContentTransformer.java | 20 +- .../src/main/resources/logback.default.xml | 2 - scm-webapp/src/main/webapp/WEB-INF/web.xml | 38 +- .../sonia.action.changepasswordwindow.js | 2 +- .../js/config/sonia.config.scmconfigpanel.js | 4 +- .../js/group/sonia.group.formpanel.js | 4 +- .../resources/js/group/sonia.group.panel.js | 2 +- .../resources/js/login/sonia.login.form.js | 15 +- .../js/plugin/sonia.plugin.center.js | 6 +- .../resources/js/plugin/sonia.plugin.grid.js | 2 +- .../sonia.repository.branchcombobox.js | 2 +- .../sonia.repository.changesetviewerpanel.js | 2 +- .../sonia.repository.commitpanel.js | 2 +- .../repository/sonia.repository.formpanel.js | 4 +- .../js/repository/sonia.repository.grid.js | 2 +- .../sonia.repository.healthcheckfailure.js | 2 +- .../sonia.repository.importwindow.js | 4 +- .../js/repository/sonia.repository.js | 2 +- .../js/repository/sonia.repository.panel.js | 4 +- .../sonia.repository.repositorybrowser.js | 2 +- .../sonia.repository.tagcombobox.js | 2 +- .../sonia.security.permissionspanel.js | 8 +- .../main/webapp/resources/js/sonia.global.js | 4 +- .../src/main/webapp/resources/js/sonia.scm.js | 2 +- .../resources/js/user/sonia.user.formpanel.js | 4 +- .../resources/js/user/sonia.user.grid.js | 2 +- .../resources/js/user/sonia.user.panel.js | 2 +- .../test/java/sonia/scm/it/GitLfsITCase.java | 7 +- 48 files changed, 878 insertions(+), 623 deletions(-) rename scm-core/src/main/java/sonia/scm/template/Viewable.java => scm-webapp/src/main/java/sonia/scm/api/rest/UriExtensionsConfig.java (52%) diff --git a/pom.xml b/pom.xml index 3674300b1d..840c9f1ec3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ sonia.scm scm pom - 2.0.0-SNAPSHOT + 1.61-SNAPSHOT The easiest way to share your Git, Mercurial and Subversion repositories over http. @@ -59,20 +59,18 @@ https://scm-manager.ci.cloudbees.com/ - - 3.1.0 - - - scm-annotations - scm-annotation-processor scm-core scm-test + maven scm-plugins + scm-samples scm-dao-xml scm-webapp scm-server + scm-plugin-backend scm-clients + support @@ -82,15 +80,6 @@ scm-manager release repository http://maven.scm-manager.org/nexus/content/groups/public - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - true - daily - - @@ -139,52 +128,20 @@ ${mokito.version} test - + - - - org.apache.maven.plugins - maven-enforcer-plugin - 1.4.1 - - - enforce-java - compile - - enforce - - - - - - [1.8.0-101,) - - - - [3.1,) - - - true - - - - org.codehaus.mojo animal-sniffer-maven-plugin - 1.15 + 1.16 org.codehaus.mojo.signature - java18 + java17 1.0 @@ -198,23 +155,51 @@ + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-java + compile + + enforce + + + + + 1.7 + + + module-info + + + + true + + + + + + org.codehaus.mojo + extra-enforcer-rules + 1.0-beta-7 + + + + org.apache.maven.plugins maven-compiler-plugin - 3.5.1 + 3.0 - true - true ${project.build.javaLevel} ${project.build.javaLevel} - ${project.test.javaLevel} - ${project.test.javaLevel} ${project.build.sourceEncoding} - - -Xlint:unchecked,-options @@ -259,7 +244,7 @@ true true - http://download.oracle.com/javase/8/docs/api/ + http://download.oracle.com/javase/7/docs/api/ http://download.oracle.com/docs/cd/E17802_01/products/products/servlet/2.5/docs/servlet-2_5-mr2/ http://jersey.java.net/nonav/apidocs/${jersey.version}/jersey/ https://google.github.io/guice/api-docs/${guice.version}/javadoc @@ -316,81 +301,59 @@ maven-eclipse-plugin 2.6 - - - - - org.jacoco - jacoco-maven-plugin - 0.7.7.201606060606 - - - - prepare-agent - - - - report - prepare-package - - report - - - - - + org.apache.maven.plugins maven-site-plugin - 3.2 - - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 2.4 - - - - org.apache.maven.plugins - maven-jxr-plugin - 2.3 - - - - org.codehaus.mojo - findbugs-maven-plugin - 2.4.0 - - - - org.apache.maven.plugins - maven-surefire-report-plugin - 2.12 - - - - org.apache.maven.plugins - maven-pmd-plugin - 2.7.1 - - true - ${project.build.sourceEncoding} - ${project.build.javaLevel} - - - - - + 3.7 + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.4.0 + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.12 + + + + org.apache.maven.plugins + maven-pmd-plugin + 2.7.1 + + ${project.build.sourceEncoding} + ${project.build.javaLevel} + + + + + + @@ -434,18 +397,9 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.8.1 + 3.0.0 - org.jboss.apiviz.APIviz - - org.jboss.apiviz - apiviz - 1.3.2.GA - - - -sourceclasspath ${project.build.outputDirectory} - -nopackagediagram - + false @@ -456,6 +410,101 @@ + + + + + + + commons-beanutils + commons-beanutils + 1.9.3 + + + + commons-collections + commons-collections + 3.2.2 + + + + + + org.apache.httpcomponents + httpclient + 4.5.5 + + + + + + slf4j-api + org.slf4j + ${slf4j.version} + + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + + + org.codehaus.jackson + jackson-core-asl + ${jackson.version} + + + + org.codehaus.jackson + jackson-mapper-asl + ${jackson.version} + + + + org.codehaus.jackson + jackson-jaxrs + ${jackson.version} + + + + org.codehaus.jackson + jackson-xc + ${jackson.version} + + + + + + javax.xml.bind + jaxb-api + ${jaxb.version} + + + + com.sun.xml.bind + jaxb-impl + ${jaxb.version} + + + + org.glassfish.jaxb + jaxb-runtime + ${jaxb.version} + + + + javax.activation + activation + 1.1.1 + + + + + @@ -479,37 +528,31 @@ 4.12 - 1.7.22 + 1.7.25 1.2.3 - 3.0.1 - 2.0.1 - 4.0 + 2.5 + 3.0 1.19.4 - - - 1.2.0 - 2.6.6 2.3.20 - - - 9.2.10.v20150310 - 9.2.10.v20150310 + 7.6.21.v20160908 + 7.6.16.v20140903 + 1.9.13 + 2.3.0 - 1.0.0-SNAPSHOT - 1.4.0-RC2 + 1.3.2 - - v4.5.2.201704071617-r-scm1 - 1.8.15-scm1 + + v4.5.3.201708160445-r-scm1 + 1.9.0-scm3 - 16.0.1 + 15.0 2.2.3 - 1.8 + 1.7 UTF-8 SCM-BSD diff --git a/scm-clients/scm-client-impl/pom.xml b/scm-clients/scm-client-impl/pom.xml index 1e6847349f..ba6edb9130 100644 --- a/scm-clients/scm-client-impl/pom.xml +++ b/scm-clients/scm-client-impl/pom.xml @@ -42,13 +42,13 @@ com.sun.jersey jersey-client - ${jersey-client.version} + ${jersey.version} com.sun.jersey.contribs jersey-multipart - ${jersey-client.version} + ${jersey.version} diff --git a/scm-core/pom.xml b/scm-core/pom.xml index fde7dceb47..ae0057dbdf 100644 --- a/scm-core/pom.xml +++ b/scm-core/pom.xml @@ -69,9 +69,9 @@ - javax.ws.rs - javax.ws.rs-api - ${jaxrs.version} + com.sun.jersey + jersey-core + ${jersey.version} diff --git a/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java b/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java index b4f0d81cd3..ddb8a699a7 100644 --- a/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java +++ b/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java @@ -45,6 +45,8 @@ import sonia.scm.util.IOUtil; //~--- JDK imports ------------------------------------------------------------ +import com.sun.jersey.core.util.Base64; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -58,7 +60,6 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; -import java.util.Base64; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; @@ -164,7 +165,7 @@ public class DefaultCipherHandler implements CipherHandler { String result = null; try { - byte[] encodedInput = Base64.getDecoder().decode(value); + byte[] encodedInput = Base64.decode(value); byte[] salt = new byte[SALT_LENGTH]; byte[] encoded = new byte[encodedInput.length - SALT_LENGTH]; @@ -221,7 +222,7 @@ public class DefaultCipherHandler implements CipherHandler { System.arraycopy(salt, 0, result, 0, SALT_LENGTH); System.arraycopy(encodedInput, 0, result, SALT_LENGTH, result.length - SALT_LENGTH); - res = new String(Base64.getEncoder().encode(result), ENCODING); + res = new String(Base64.encode(result), ENCODING); } catch (IOException | GeneralSecurityException ex) { throw new CipherException("could not encode string", ex); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index 0befcf6f11..1fb78161e0 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -36,7 +36,6 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.base.Stopwatch; -import com.google.common.base.Strings; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -53,21 +52,18 @@ import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.RepositoryRequestListenerUtil; -import sonia.scm.security.CipherUtil; import sonia.scm.util.AssertUtil; -import sonia.scm.util.HttpUtil; import sonia.scm.web.cgi.CGIExecutor; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.EnvList; //~--- JDK imports ------------------------------------------------------------ -import com.sun.jersey.core.util.Base64; - import java.io.File; import java.io.IOException; import java.util.Enumeration; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -83,17 +79,18 @@ import javax.servlet.http.HttpSession; public class HgCGIServlet extends HttpServlet { + private static final String ENV_PYTHON_HTTPS_VERIFY = "PYTHONHTTPSVERIFY"; + /** Field description */ public static final String ENV_REPOSITORY_NAME = "REPO_NAME"; /** Field description */ public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH"; - /** Field description */ - public static final String ENV_SESSION_PREFIX = "SCM_"; + private static final String ENV_HTTP_POST_ARGS = "SCM_HTTP_POST_ARGS"; /** Field description */ - private static final String SCM_CREDENTIALS = "SCM_CREDENTIALS"; + public static final String ENV_SESSION_PREFIX = "SCM_"; /** Field description */ private static final long serialVersionUID = -3492811300905099810L; @@ -231,7 +228,6 @@ public class HgCGIServlet extends HttpServlet * @param env * @param session */ - @SuppressWarnings("unchecked") private void passSessionAttributes(EnvList env, HttpSession session) { Enumeration enm = session.getAttributeNames(); @@ -277,19 +273,27 @@ public class HgCGIServlet extends HttpServlet directory.getAbsolutePath()); // add hook environment + Map environment = executor.getEnvironment().asMutableMap(); + if (handler.getConfig().isDisableHookSSLValidation()) { + // disable ssl validation + // Issue 959: https://goo.gl/zH5eY8 + environment.put(ENV_PYTHON_HTTPS_VERIFY, "0"); + } + + // enable experimental httppostargs protocol of mercurial + // Issue 970: https://goo.gl/poascp + environment.put(ENV_HTTP_POST_ARGS, String.valueOf(handler.getConfig().isEnableHttpPostArgs())); + //J- HgEnvironment.prepareEnvironment( - executor.getEnvironment().asMutableMap(), + environment, handler, - hookManager, + hookManager, request ); //J+ - addCredentials(executor.getEnvironment(), request); - - // unused ??? - HttpSession session = request.getSession(false); + HttpSession session = request.getSession(); if (session != null) { diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index b22ceccb90..3803b24e00 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -6,54 +6,63 @@ sonia.scm scm - 2.0.0-SNAPSHOT + 1.61-SNAPSHOT sonia.scm scm-webapp war - 2.0.0-SNAPSHOT + 1.61-SNAPSHOT scm-webapp - - - - sonia.scm - scm-annotation-processor - 2.0.0-SNAPSHOT - provided - - javax.servlet - javax.servlet-api + servlet-api ${servlet.version} provided - - + + javax.transaction jta 1.1 provided - + - + sonia.scm scm-core - 2.0.0-SNAPSHOT + 1.61-SNAPSHOT - + sonia.scm scm-dao-xml - 2.0.0-SNAPSHOT + 1.61-SNAPSHOT + + + + sonia.scm.plugins + scm-hg-plugin + 1.61-SNAPSHOT + + + + sonia.scm.plugins + scm-svn-plugin + 1.61-SNAPSHOT + + + + sonia.scm.plugins + scm-git-plugin + 1.61-SNAPSHOT @@ -63,18 +72,12 @@ shiro-web ${shiro.version} - + org.apache.shiro shiro-guice ${shiro.version} - - - io.jsonwebtoken - jjwt - 0.4 - @@ -113,13 +116,13 @@ provided - + com.sun.jersey.contribs jersey-multipart ${jersey.version} - + @@ -127,66 +130,73 @@ guice-multibindings ${guice.version} - - - - - com.github.legman.support - shiro - ${legman.version} - - + ch.qos.logback logback-classic - ${logback.version} - + org.slf4j jcl-over-slf4j ${slf4j.version} - + org.slf4j log4j-over-slf4j ${slf4j.version} - + + + + + net.sf.ehcache + ehcache-core + ${ehcache.version} + + + + + + xml-apis + xml-apis + 1.4.01 + + - + commons-beanutils commons-beanutils - 1.9.2 - + commons-collections commons-collections - 3.2.1 - - - + commons-codec commons-codec 1.9 - + com.google.guava guava ${guava.version} - + org.quartz-scheduler quartz @@ -198,25 +208,67 @@ - - - - - org.apache.httpcomponents - httpclient - 4.2.6 - - + - + + + org.freemarker + freemarker + ${freemarker.version} + + com.github.spullara.mustache.java compiler ${mustache.version} - + + + + + org.eclipse.aether + aether-api + ${aether.version} + + + + org.eclipse.aether + aether-impl + ${aether.version} + + + + org.apache.maven + maven-aether-provider + ${maven.version} + + + plexus-component-annotations + org.codehaus.plexus + + + + + + org.eclipse.aether + aether-transport-http + ${aether.version} + + + + org.eclipse.aether + aether-transport-file + ${aether.version} + + + + org.eclipse.aether + aether-connector-basic + ${aether.version} + + - + com.webcohesion.enunciate enunciate-core-annotations @@ -228,7 +280,7 @@ sonia.scm scm-test - 2.0.0-SNAPSHOT + 1.61-SNAPSHOT test @@ -237,7 +289,31 @@ - + + + sonia.scm.plugins + scm-git-plugin + 1.61-SNAPSHOT + tests + test + + + + sonia.scm.plugins + scm-hg-plugin + 1.61-SNAPSHOT + tests + test + + + + sonia.scm.plugins + scm-svn-plugin + 1.61-SNAPSHOT + tests + test + + org.seleniumhq.selenium selenium-java @@ -251,7 +327,7 @@ ${selenium.version} test - + org.seleniumhq.selenium htmlunit-driver @@ -272,71 +348,23 @@ ${jersey.version} test - - - - + com.github.sdorra shiro-unit 1.0.0 test - - - sonia.scm.plugins - scm-git-plugin - 2.0.0-SNAPSHOT - tests - test - - - - sonia.scm.plugins - scm-git-plugin - 2.0.0-SNAPSHOT - test - - - - sonia.scm.plugins - scm-hg-plugin - 2.0.0-SNAPSHOT - tests - test - - - - sonia.scm.plugins - scm-hg-plugin - 2.0.0-SNAPSHOT - test - - - - sonia.scm.plugins - scm-svn-plugin - 2.0.0-SNAPSHOT - tests - test - - - - sonia.scm.plugins - scm-svn-plugin - 2.0.0-SNAPSHOT - test - - + - + commons-logging commons-logging 1.1.3 provided - + log4j log4j @@ -347,8 +375,9 @@ + - + com.mycila.maven-license-plugin maven-license-plugin @@ -371,6 +400,7 @@ + org.apache.maven.plugins maven-dependency-plugin @@ -388,49 +418,39 @@ - + - sonia.scm.maven - smp-maven-plugin - 1.0.0-alpha-2 - - - - sonia.scm.plugins - scm-hg-plugin - ${project.version} - smp - - - sonia.scm.plugins - scm-svn-plugin - ${project.version} - smp - - - sonia.scm.plugins - scm-git-plugin - ${project.version} - smp - - - sonia.scm.plugins - scm-legacy-plugin - ${project.version} - smp - - - + org.apache.maven.plugins + maven-antrun-plugin + 1.6 + repack compile - copy-core-plugins + run + + + + + + + + + + + + + + + - + org.apache.maven.plugins maven-war-plugin @@ -444,7 +464,7 @@ - + sonia.maven change-env @@ -464,7 +484,7 @@ - org.eclipse.jetty + org.mortbay.jetty jetty-maven-plugin ${jetty.maven.version} @@ -484,14 +504,23 @@ true + + + 8081 + 60000 + 16384 + + /scm - ${project.basedir}/src/main/conf/jetty.xml + ${project.build.javaLevel} + ${project.build.javaLevel} + ${project.build.sourceEncoding} 0 - - + + scm-webapp @@ -503,7 +532,9 @@ default 2.53.1 2.9.1 + 1.1.0 1.0 + 3.3.9 0.8.17 Tomcat e1 @@ -513,7 +544,21 @@ - + + + cluster + + + + + sonia.scm + scm-dao-orientdb + 1.58-SNAPSHOT + + + + + release @@ -594,7 +639,7 @@ - org.eclipse.jetty + org.mortbay.jetty jetty-maven-plugin ${jetty.maven.version} @@ -610,7 +655,16 @@ ${scm.stage} - ${project.basedir}/src/main/conf/jetty.xml + + + 8081 + 60000 + 16384 + + + ${project.build.javaLevel} + ${project.build.javaLevel} + ${project.build.sourceEncoding} 0 true @@ -631,29 +685,29 @@ - + - + selenium - + - + org.apache.httpcomponents httpclient 4.3.2 test - + - + - + org.apache.maven.plugins maven-failsafe-plugin @@ -678,15 +732,12 @@ - + - org.eclipse.jetty + org.mortbay.jetty jetty-maven-plugin ${jetty.maven.version} - - 8082 - 8086 STOP @@ -695,7 +746,16 @@ target/scm-it - ${project.basedir}/src/main/conf/jetty.xml + + + 8082 + 60000 + 16384 + + + ${project.build.javaLevel} + ${project.build.javaLevel} + ${project.build.sourceEncoding} 0 true @@ -716,7 +776,7 @@ - + org.codehaus.mojo selenium-maven-plugin @@ -737,22 +797,22 @@ post-integration-test stop-server - + - + - + - + doc - + - + org.apache.maven.plugins maven-resources-plugin @@ -766,7 +826,7 @@ ${project.build.directory} - + src/main/doc true @@ -774,12 +834,12 @@ **/enunciate.xml - - + + - + com.webcohesion.enunciate enunciate-maven-plugin @@ -811,7 +871,7 @@ - + org.apache.maven.plugins maven-assembly-plugin @@ -830,12 +890,12 @@ - + - + diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 12c30fd152..1b8e0c7803 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -35,13 +35,15 @@ package sonia.scm; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.collect.Maps; import com.google.inject.Provider; import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; import com.google.inject.servlet.RequestScoped; +import com.google.inject.servlet.ServletModule; import com.google.inject.throwingproviders.ThrowingProviderBinder; +import org.apache.shiro.authz.permission.PermissionResolver; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,6 +52,11 @@ import sonia.scm.cache.CacheManager; import sonia.scm.cache.GuavaCacheManager; import sonia.scm.config.ScmConfiguration; import sonia.scm.event.ScmEventBus; +import sonia.scm.filter.AdminSecurityFilter; +import sonia.scm.filter.BaseUrlFilter; +import sonia.scm.filter.GZipFilter; +import sonia.scm.filter.MDCFilter; +import sonia.scm.filter.SecurityFilter; import sonia.scm.group.DefaultGroupManager; import sonia.scm.group.GroupDAO; import sonia.scm.group.GroupManager; @@ -57,14 +64,20 @@ import sonia.scm.group.GroupManagerProvider; import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.io.DefaultFileSystem; import sonia.scm.io.FileSystem; +import sonia.scm.net.HttpClient; +import sonia.scm.net.URLHttpClient; import sonia.scm.plugin.DefaultPluginLoader; import sonia.scm.plugin.DefaultPluginManager; +import sonia.scm.plugin.Plugin; import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginManager; +import sonia.scm.repository.ChangesetViewerUtil; import sonia.scm.repository.DefaultRepositoryManager; import sonia.scm.repository.DefaultRepositoryProvider; import sonia.scm.repository.HealthCheckContextListener; +import sonia.scm.repository.LastModifiedUpdateListener; import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryBrowserUtil; import sonia.scm.repository.RepositoryDAO; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryManagerProvider; @@ -79,9 +92,15 @@ import sonia.scm.resources.ResourceManager; import sonia.scm.resources.ScriptResourceServlet; import sonia.scm.security.CipherHandler; import sonia.scm.security.CipherUtil; +import sonia.scm.security.ConfigurableLoginAttemptHandler; import sonia.scm.security.DefaultKeyGenerator; import sonia.scm.security.DefaultSecuritySystem; +import sonia.scm.security.EncryptionHandler; import sonia.scm.security.KeyGenerator; +import sonia.scm.security.LoginAttemptHandler; +import sonia.scm.security.MessageDigestEncryptionHandler; +import sonia.scm.security.RepositoryPermissionResolver; +import sonia.scm.security.SecurityContext; import sonia.scm.security.SecuritySystem; import sonia.scm.store.BlobStoreFactory; import sonia.scm.store.ConfigurationEntryStoreFactory; @@ -89,10 +108,16 @@ import sonia.scm.store.DataStoreFactory; import sonia.scm.store.FileBlobStoreFactory; import sonia.scm.store.JAXBConfigurationEntryStoreFactory; import sonia.scm.store.JAXBDataStoreFactory; -import sonia.scm.store.JAXBConfigurationStoreFactory; +import sonia.scm.store.JAXBStoreFactory; +import sonia.scm.store.ListenableStoreFactory; +import sonia.scm.store.StoreFactory; +import sonia.scm.template.DefaultEngine; +import sonia.scm.template.FreemarkerTemplateEngine; +import sonia.scm.template.FreemarkerTemplateHandler; import sonia.scm.template.MustacheTemplateEngine; import sonia.scm.template.TemplateEngine; import sonia.scm.template.TemplateEngineFactory; +import sonia.scm.template.TemplateHandler; import sonia.scm.template.TemplateServlet; import sonia.scm.url.RestJsonUrlProvider; import sonia.scm.url.RestXmlUrlProvider; @@ -108,16 +133,21 @@ import sonia.scm.util.DebugServlet; import sonia.scm.util.ScmConfigurationUtil; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.DefaultCGIExecutorFactory; +import sonia.scm.web.filter.AutoLoginFilter; import sonia.scm.web.filter.LoggingFilter; import sonia.scm.web.security.AdministrationContext; +import sonia.scm.web.security.ApiBasicAuthenticationFilter; +import sonia.scm.web.security.AuthenticationManager; +import sonia.scm.web.security.BasicSecurityContext; +import sonia.scm.web.security.ChainAuthenticatonManager; import sonia.scm.web.security.DefaultAdministrationContext; +import sonia.scm.web.security.WebSecurityContext; //~--- JDK imports ------------------------------------------------------------ import com.sun.jersey.api.core.PackagesResourceConfig; import com.sun.jersey.api.core.ResourceConfig; import com.sun.jersey.api.json.JSONConfiguration; -import com.sun.jersey.guice.JerseyServletModule; import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; import com.sun.jersey.spi.container.servlet.ServletContainer; @@ -127,10 +157,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; - -import javax.servlet.ServletContext; -import sonia.scm.store.ConfigurationStoreFactory; - import javax.net.ssl.SSLContext; import sonia.scm.net.SSLContextProvider; import sonia.scm.net.ahc.AdvancedHttpClient; @@ -140,16 +166,15 @@ import sonia.scm.net.ahc.JsonContentTransformer; import sonia.scm.net.ahc.XmlContentTransformer; import sonia.scm.schedule.QuartzScheduler; import sonia.scm.schedule.Scheduler; -import sonia.scm.security.ConfigurableLoginAttemptHandler; -import sonia.scm.security.LoginAttemptHandler; import sonia.scm.security.AuthorizationChangedEventProducer; +import sonia.scm.security.XsrfProtectionFilter; import sonia.scm.web.UserAgentParser; /** * * @author Sebastian Sdorra */ -public class ScmServletModule extends JerseyServletModule +public class ScmServletModule extends ServletModule { /** Field description */ @@ -214,15 +239,11 @@ public class ScmServletModule extends JerseyServletModule * Constructs ... * * - * - * @param servletContext * @param pluginLoader * @param overrides */ - ScmServletModule(ServletContext servletContext, - DefaultPluginLoader pluginLoader, ClassOverrides overrides) + ScmServletModule(DefaultPluginLoader pluginLoader, ClassOverrides overrides) { - this.servletContext = servletContext; this.pluginLoader = pluginLoader; this.overrides = overrides; } @@ -242,24 +263,22 @@ public class ScmServletModule extends JerseyServletModule bind(SCMContextProvider.class).toInstance(context); - ScmConfiguration config = getScmConfiguration(); + ScmConfiguration config = getScmConfiguration(context); CipherUtil cu = CipherUtil.getInstance(); - + // bind repository provider ThrowingProviderBinder.create(binder()).bind( RepositoryProvider.class, Repository.class).to( DefaultRepositoryProvider.class).in(RequestScoped.class); - // bind servlet context - bind(ServletContext.class).annotatedWith(Default.class).toInstance( - servletContext); - // bind event api bind(ScmEventBus.class).toInstance(ScmEventBus.getInstance()); // bind core - bind(ConfigurationStoreFactory.class, JAXBConfigurationStoreFactory.class); - bind(ConfigurationEntryStoreFactory.class, JAXBConfigurationEntryStoreFactory.class); + bind(StoreFactory.class, JAXBStoreFactory.class); + bind(ListenableStoreFactory.class, JAXBStoreFactory.class); + bind(ConfigurationEntryStoreFactory.class, + JAXBConfigurationEntryStoreFactory.class); bind(DataStoreFactory.class, JAXBDataStoreFactory.class); bind(BlobStoreFactory.class, FileBlobStoreFactory.class); bind(ScmConfiguration.class).toInstance(config); @@ -272,20 +291,24 @@ public class ScmServletModule extends JerseyServletModule // note CipherUtil uses an other generator bind(KeyGenerator.class).to(DefaultKeyGenerator.class); bind(CipherHandler.class).toInstance(cu.getCipherHandler()); + bind(EncryptionHandler.class, MessageDigestEncryptionHandler.class); bind(FileSystem.class, DefaultFileSystem.class); // bind health check stuff bind(HealthCheckContextListener.class); // bind extensions - pluginLoader.getExtensionProcessor().processAutoBindExtensions(binder()); + pluginLoader.processExtensions(binder()); // bind security stuff - bind(LoginAttemptHandler.class).to(ConfigurableLoginAttemptHandler.class); bind(AuthorizationChangedEventProducer.class); - + bind(PermissionResolver.class, RepositoryPermissionResolver.class); + bind(AuthenticationManager.class, ChainAuthenticatonManager.class); + bind(SecurityContext.class).to(BasicSecurityContext.class); + bind(WebSecurityContext.class).to(BasicSecurityContext.class); bind(SecuritySystem.class).to(DefaultSecuritySystem.class); bind(AdministrationContext.class, DefaultAdministrationContext.class); + bind(LoginAttemptHandler.class, ConfigurableLoginAttemptHandler.class); // bind cache bind(CacheManager.class, GuavaCacheManager.class); @@ -303,10 +326,14 @@ public class ScmServletModule extends JerseyServletModule bindDecorated(GroupManager.class, DefaultGroupManager.class, GroupManagerProvider.class); bind(CGIExecutorFactory.class, DefaultCGIExecutorFactory.class); + bind(ChangesetViewerUtil.class); + bind(RepositoryBrowserUtil.class); // bind sslcontext provider bind(SSLContext.class).toProvider(SSLContextProvider.class); + // bind httpclient + bind(HttpClient.class, URLHttpClient.class); // bind ahc Multibinder transformers = @@ -351,7 +378,24 @@ public class ScmServletModule extends JerseyServletModule { filter(PATTERN_ALL).through(LoggingFilter.class); } + + // protect api agains xsrf attacks + filter(PATTERN_RESTAPI).through(XsrfProtectionFilter.class); + /* + * filter(PATTERN_PAGE, + * PATTERN_STATIC_RESOURCES).through(StaticResourceFilter.class); + */ + filter(PATTERN_ALL).through(BaseUrlFilter.class); + filter(PATTERN_ALL).through(AutoLoginFilter.class); + filterRegex(RESOURCE_REGEX).through(GZipFilter.class); + filter(PATTERN_RESTAPI, PATTERN_DEBUG).through(ApiBasicAuthenticationFilter.class); + filter(PATTERN_RESTAPI, PATTERN_DEBUG).through(SecurityFilter.class); + filter(PATTERN_CONFIG, PATTERN_ADMIN).through(AdminSecurityFilter.class); + + // added mdcs for logging + filter(PATTERN_ALL).through(MDCFilter.class); + // debug servlet serve(PATTERN_DEBUG).with(DebugServlet.class); @@ -359,21 +403,23 @@ public class ScmServletModule extends JerseyServletModule serve(PATTERN_PLUGIN_SCRIPT).with(ScriptResourceServlet.class); // template + bind(TemplateHandler.class).to(FreemarkerTemplateHandler.class); serve(PATTERN_INDEX, "/").with(TemplateServlet.class); Multibinder engineBinder = Multibinder.newSetBinder(binder(), TemplateEngine.class); engineBinder.addBinding().to(MustacheTemplateEngine.class); - bind(TemplateEngine.class).annotatedWith(Default.class).to( + engineBinder.addBinding().to(FreemarkerTemplateEngine.class); + bind(TemplateEngine.class).annotatedWith(DefaultEngine.class).to( MustacheTemplateEngine.class); bind(TemplateEngineFactory.class); // bind events - // bind(LastModifiedUpdateListener.class); + bind(LastModifiedUpdateListener.class); // jersey - Map params = Maps.newHashMap(); + Map params = new HashMap(); /* * params.put("com.sun.jersey.spi.container.ContainerRequestFilters", @@ -386,17 +432,63 @@ public class ScmServletModule extends JerseyServletModule params.put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE.toString()); params.put(ResourceConfig.FEATURE_REDIRECT, Boolean.TRUE.toString()); params.put(ResourceConfig.FEATURE_DISABLE_WADL, Boolean.TRUE.toString()); - - /* - * TODO remove UriExtensionsConfig and PackagesResourceConfig - * to stop jersey classpath scanning - */ params.put(ServletContainer.RESOURCE_CONFIG_CLASS, UriExtensionsConfig.class.getName()); - params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "unbound"); + + String restPath = getRestPackages(); + logger.info("configure jersey with package path: {}", restPath); + + params.put(PackagesResourceConfig.PROPERTY_PACKAGES, restPath); serve(PATTERN_RESTAPI).with(GuiceContainer.class, params); } + /** + * Method description + * + * + * @param packageSet + * @param plugin + */ + private void appendPluginPackages(Set packageSet, Plugin plugin) + { + Set pluginPackageSet = plugin.getPackageSet(); + + if (pluginPackageSet != null) + { + for (String pluginPkg : pluginPackageSet) + { + boolean append = true; + + for (String pkg : packageSet) + { + if (pluginPkg.startsWith(pkg)) + { + append = false; + + break; + } + } + + if (append) + { + if (logger.isDebugEnabled()) + { + String name = "unknown"; + + if (plugin.getInformation() != null) + { + name = plugin.getInformation().getName(); + } + + logger.debug("plugin {} added rest path {}", name, pluginPkg); + } + + packageSet.add(pluginPkg); + } + } + } + } + /** * Method description * @@ -484,6 +576,44 @@ public class ScmServletModule extends JerseyServletModule //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + private String getRestPackages() + { + Set packageSet = new HashSet(); + + packageSet.add(SCMContext.DEFAULT_PACKAGE); + + Collection plugins = pluginLoader.getInstalledPlugins(); + + if (plugins != null) + { + for (Plugin plugin : plugins) + { + appendPluginPackages(packageSet, plugin); + } + } + + StringBuilder buffer = new StringBuilder(); + Iterator pkgIterator = packageSet.iterator(); + + while (pkgIterator.hasNext()) + { + buffer.append(pkgIterator.next()); + + if (pkgIterator.hasNext()) + { + buffer.append(";"); + } + } + + return buffer.toString(); + } + /** * Load ScmConfiguration with JAXB * @@ -492,7 +622,7 @@ public class ScmServletModule extends JerseyServletModule * * @return */ - private ScmConfiguration getScmConfiguration() + private ScmConfiguration getScmConfiguration(SCMContextProvider context) { ScmConfiguration configuration = new ScmConfiguration(); @@ -504,11 +634,8 @@ public class ScmServletModule extends JerseyServletModule //~--- fields --------------------------------------------------------------- /** Field description */ - private final ClassOverrides overrides; + private ClassOverrides overrides; /** Field description */ - private final DefaultPluginLoader pluginLoader; - - /** Field description */ - private final ServletContext servletContext; + private DefaultPluginLoader pluginLoader; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/TemplateEngineViewable.java b/scm-webapp/src/main/java/sonia/scm/api/rest/TemplateEngineViewable.java index b36cf6c7e7..4a089ab150 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/TemplateEngineViewable.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/TemplateEngineViewable.java @@ -42,50 +42,65 @@ import sonia.scm.template.TemplateEngineFactory; //~--- JDK imports ------------------------------------------------------------ +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.spi.template.ViewProcessor; + import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; -import sonia.scm.template.Viewable; /** * * @author Sebastian Sdorra */ @Provider -public class TemplateEngineViewable implements MessageBodyWriter +public class TemplateEngineViewable implements ViewProcessor { - - private final TemplateEngineFactory templateEngineFactory; + /** + * Constructs ... + * + * + * @param templateEngineFactory + */ @Inject public TemplateEngineViewable(TemplateEngineFactory templateEngineFactory) { this.templateEngineFactory = templateEngineFactory; } + //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param name + * + * @return + */ @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return type.isAssignableFrom(Viewable.class); + public String resolve(String name) + { + return name; } + /** + * Method description + * + * + * @param path + * @param viewable + * @param out + * + * @throws IOException + */ @Override - public long getSize(Viewable viewable, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return -1; - } - - @Override - public void writeTo(Viewable viewable, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { - String path = viewable.getPath(); - + public void writeTo(String path, Viewable viewable, OutputStream out) + throws IOException + { TemplateEngine engine = templateEngineFactory.getEngineByExtension(path); if (engine == null) @@ -100,9 +115,14 @@ public class TemplateEngineViewable implements MessageBodyWriter throw new IOException("could not find template for ".concat(path)); } - PrintWriter writer = new PrintWriter(entityStream); + PrintWriter writer = new PrintWriter(out); - template.execute(writer, viewable.getContext()); + template.execute(writer, viewable.getModel()); writer.flush(); } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private TemplateEngineFactory templateEngineFactory; } diff --git a/scm-core/src/main/java/sonia/scm/template/Viewable.java b/scm-webapp/src/main/java/sonia/scm/api/rest/UriExtensionsConfig.java similarity index 52% rename from scm-core/src/main/java/sonia/scm/template/Viewable.java rename to scm-webapp/src/main/java/sonia/scm/api/rest/UriExtensionsConfig.java index 8344d2820e..637866ad61 100644 --- a/scm-core/src/main/java/sonia/scm/template/Viewable.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/UriExtensionsConfig.java @@ -28,63 +28,89 @@ * http://bitbucket.org/sdorra/scm-manager * */ -package sonia.scm.template; -import com.google.common.base.Objects; +package sonia.scm.api.rest; + +//~--- JDK imports ------------------------------------------------------------ + +import com.sun.jersey.api.core.PackagesResourceConfig; + +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + /** - * A viewable holds the path to a template and the context object which is used to render the template. Viewables can - * be used as return type of jax-rs resources. - * + * * @author Sebastian Sdorra - * @since 2.0.0 */ -public final class Viewable { - - private final String path; - private final Object context; +public class UriExtensionsConfig extends PackagesResourceConfig +{ - public Viewable(String path, Object context) { - this.path = path; - this.context = context; + /** Field description */ + public static final String EXTENSION_JSON = "json"; + + /** Field description */ + public static final String EXTENSION_XML = "xml"; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public UriExtensionsConfig() + { + super(); } - public String getPath() { - return path; + /** + * Constructs ... + * + * + * @param props + */ + public UriExtensionsConfig(Map props) + { + super(props); } - public Object getContext() { - return context; + /** + * Constructs ... + * + * + * @param paths + */ + public UriExtensionsConfig(String[] paths) + { + super(paths); } + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ @Override - public int hashCode() { - return Objects.hashCode(path, context); + public Map getMediaTypeMappings() + { + if (mediaTypeMap == null) + { + mediaTypeMap = new HashMap(); + mediaTypeMap.put(EXTENSION_JSON, MediaType.APPLICATION_JSON_TYPE); + mediaTypeMap.put(EXTENSION_XML, MediaType.APPLICATION_XML_TYPE); + } + + return mediaTypeMap; } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Viewable other = (Viewable) obj; - return !Objects.equal(this.path, other.path) - && Objects.equal(this.context, other.context); - } + //~--- fields --------------------------------------------------------------- - @Override - public String toString() { - return Objects.toStringHelper(this) - .add("path", path) - .add("context", context) - .toString(); - } - + /** Field description */ + private Map mediaTypeMap; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java index 040eb6b2dc..e9e63d16d8 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractPermissionResource.java @@ -133,7 +133,7 @@ public abstract class AbstractPermissionResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response add(@Context UriInfo uriInfo, Permission permission) { AssignedPermission ap = transformPermission(permission); @@ -185,7 +185,7 @@ public abstract class AbstractPermissionResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response update(@PathParam("id") String id, Permission permission) { StoredAssignedPermission sap = getPermission(id); @@ -213,7 +213,7 @@ public abstract class AbstractPermissionResource @ResponseCode(code = 404, condition = "not found, no permission with the specified id available"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Permission get(@PathParam("id") String id) { StoredAssignedPermission sap = getPermission(id); @@ -231,7 +231,7 @@ public abstract class AbstractPermissionResource @ResponseCode(code = 204, condition = "success"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public List getAll() { return getPermissions(getPredicate()); diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ChangePasswordResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ChangePasswordResource.java index 87626c7045..52b8b02c37 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ChangePasswordResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ChangePasswordResource.java @@ -118,7 +118,7 @@ public class ChangePasswordResource @ResponseCode(code = 400, condition = "bad request, the old password is not correct"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response changePassword(@FormParam("old-password") String oldPassword, @FormParam("new-password") String newPassword) throws UserException, IOException diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ConfigurationResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ConfigurationResource.java index a9beea7679..2fb6bdda3d 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ConfigurationResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/ConfigurationResource.java @@ -89,7 +89,7 @@ public class ConfigurationResource * @return */ @GET - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response getConfiguration() { Response response = null; @@ -118,7 +118,7 @@ public class ConfigurationResource * @return */ @POST - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response setConfig(@Context UriInfo uriInfo, ScmConfiguration newConfig) { diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java index dd61f0aecb..808aaa498b 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java @@ -119,7 +119,7 @@ public class GroupResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response create(@Context UriInfo uriInfo, Group group) { @@ -164,7 +164,7 @@ public class GroupResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response update(@Context UriInfo uriInfo, @PathParam("id") String name, Group group) @@ -191,7 +191,7 @@ public class GroupResource @ResponseCode(code = 404, condition = "not found, no group with the specified id/name available"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response get(@Context Request request, @PathParam("id") String id) { @@ -221,7 +221,7 @@ public class GroupResource * @return */ @GET - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @TypeHint(Group[].class) @StatusCodes({ @ResponseCode(code = 200, condition = "success"), diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java index fda978b3fe..54c9369a57 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java @@ -52,6 +52,7 @@ import sonia.scm.plugin.PluginInformationComparator; //~--- JDK imports ------------------------------------------------------------ +import com.sun.jersey.multipart.FormDataParam; import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.TypeHint; @@ -65,7 +66,6 @@ import java.util.Iterator; import java.util.List; import javax.ws.rs.Consumes; -import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; @@ -124,9 +124,9 @@ public class PluginResource @ResponseCode(code = 500, condition = "internal server error") }) @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response install( - /*@FormParam("package")*/ InputStream uploadedInputStream) + @FormDataParam("package") InputStream uploadedInputStream) throws IOException { Response response = null; @@ -194,7 +194,7 @@ public class PluginResource @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_HTML) public Response installFromUI( - /*@FormParam("package")*/ InputStream uploadedInputStream) + @FormDataParam("package") InputStream uploadedInputStream) throws IOException { return install(uploadedInputStream); @@ -257,7 +257,7 @@ public class PluginResource @ResponseCode(code = 200, condition = "success"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Collection getAll() { return pluginManager.getAll(); @@ -274,7 +274,7 @@ public class PluginResource @ResponseCode(code = 200, condition = "success"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Collection getAvailable() { return pluginManager.getAvailable(); @@ -291,7 +291,7 @@ public class PluginResource @ResponseCode(code = 200, condition = "success"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Collection getAvailableUpdates() { return pluginManager.getAvailableUpdates(); @@ -325,7 +325,7 @@ public class PluginResource @ResponseCode(code = 200, condition = "success"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Collection getOverview() { //J- diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java index 9c01e3d4a8..9382f58c5c 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryImportResource.java @@ -69,6 +69,8 @@ import static com.google.common.base.Preconditions.*; //~--- JDK imports ------------------------------------------------------------ +import com.sun.jersey.api.client.ClientResponse.Status; +import com.sun.jersey.multipart.FormDataParam; import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseHeader; import com.webcohesion.enunciate.metadata.rs.StatusCodes; @@ -87,7 +89,6 @@ import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; -import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; @@ -110,7 +111,7 @@ import javax.xml.bind.annotation.XmlRootElement; * * @author Sebastian Sdorra */ -// @Path("import/repositories") +@Path("import/repositories") public class RepositoryImportResource { @@ -169,8 +170,8 @@ public class RepositoryImportResource @TypeHint(TypeHint.NO_CONTENT.class) @Consumes(MediaType.MULTIPART_FORM_DATA) public Response importFromBundle(@Context UriInfo uriInfo, - @PathParam("type") String type, @FormParam("name") String name, - @FormParam("bundle") InputStream inputStream, @QueryParam("compressed") + @PathParam("type") String type, @FormDataParam("name") String name, + @FormDataParam("bundle") InputStream inputStream, @QueryParam("compressed") @DefaultValue("false") boolean compressed) { Repository repository = doImportFromBundle(type, name, inputStream, @@ -210,8 +211,8 @@ public class RepositoryImportResource @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_HTML) public Response importFromBundleUI(@PathParam("type") String type, - @FormParam("name") String name, - @FormParam("bundle") InputStream inputStream, @QueryParam("compressed") + @FormDataParam("name") String name, + @FormDataParam("bundle") InputStream inputStream, @QueryParam("compressed") @DefaultValue("false") boolean compressed) { Response response; @@ -259,7 +260,7 @@ public class RepositoryImportResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response importFromUrl(@Context UriInfo uriInfo, @PathParam("type") String type, UrlImportRequest request) { @@ -319,7 +320,7 @@ public class RepositoryImportResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(Repository[].class) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response importRepositories(@PathParam("type") String type) { SecurityUtils.getSubject().checkRole(Role.ADMIN); @@ -351,7 +352,7 @@ public class RepositoryImportResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(Repository[].class) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response importRepositories() { SecurityUtils.getSubject().checkRole(Role.ADMIN); @@ -393,7 +394,7 @@ public class RepositoryImportResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(ImportResult.class) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response importRepositoriesFromDirectory( @PathParam("type") String type) { @@ -434,7 +435,7 @@ public class RepositoryImportResource .warn( "import feature is not supported by repository handler for type " .concat(type), ex); - response = Response.status(Response.Status.BAD_REQUEST).build(); + response = Response.status(Status.BAD_REQUEST).build(); } catch (IOException ex) { @@ -450,7 +451,7 @@ public class RepositoryImportResource else { logger.warn("could not find reposiotry handler for type {}", type); - response = Response.status(Response.Status.BAD_REQUEST).build(); + response = Response.status(Status.BAD_REQUEST).build(); } return response; @@ -474,7 +475,7 @@ public class RepositoryImportResource ), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response getImportableTypes() { SecurityUtils.getSubject().checkRole(Role.ADMIN); diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java index e9f7812ee0..16168aefc7 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java @@ -166,7 +166,7 @@ public class RepositoryResource extends AbstractManagerResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response create(@Context UriInfo uriInfo, User user) { @@ -170,7 +170,7 @@ public class UserResource extends AbstractManagerResource @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response update(@Context UriInfo uriInfo, @PathParam("id") String name, User user) @@ -197,7 +197,7 @@ public class UserResource extends AbstractManagerResource @ResponseCode(code = 404, condition = "not found, no group with the specified id/name available"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response get(@Context Request request, @PathParam("id") String id) { @@ -233,7 +233,7 @@ public class UserResource extends AbstractManagerResource @ResponseCode(code = 403, condition = "forbidden, the current user has no admin privileges"), @ResponseCode(code = 500, condition = "internal server error") }) - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Override public Response getAll(@Context Request request, @DefaultValue("0") @QueryParam("start") int start, @DefaultValue("-1") diff --git a/scm-webapp/src/main/java/sonia/scm/debug/DebugResource.java b/scm-webapp/src/main/java/sonia/scm/debug/DebugResource.java index 0933242b49..f65e0c7708 100644 --- a/scm-webapp/src/main/java/sonia/scm/debug/DebugResource.java +++ b/scm-webapp/src/main/java/sonia/scm/debug/DebugResource.java @@ -67,7 +67,7 @@ public final class DebugResource * @return all received hook data for the given repository */ @GET - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Collection getAll(@PathParam("repository") String repository){ return debugService.getAll(repository); } @@ -81,7 +81,7 @@ public final class DebugResource */ @GET @Path("last") - @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public DebugHookData getLast(@PathParam("repository") String repository){ return debugService.getLast(repository); } diff --git a/scm-webapp/src/main/java/sonia/scm/net/ahc/JsonContentTransformer.java b/scm-webapp/src/main/java/sonia/scm/net/ahc/JsonContentTransformer.java index 2998f82890..5e61ed6965 100644 --- a/scm-webapp/src/main/java/sonia/scm/net/ahc/JsonContentTransformer.java +++ b/scm-webapp/src/main/java/sonia/scm/net/ahc/JsonContentTransformer.java @@ -33,16 +33,14 @@ package sonia.scm.net.ahc; //~--- non-JDK imports -------------------------------------------------------- -import com.fasterxml.jackson.databind.AnnotationIntrospector; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair; -import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; -import com.fasterxml.jackson.databind.type.TypeFactory; -import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; - import com.google.common.io.ByteSource; +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + import sonia.scm.plugin.ext.Extension; import sonia.scm.util.IOUtil; @@ -75,12 +73,12 @@ public class JsonContentTransformer implements ContentTransformer // allow jackson and jaxb annotations AnnotationIntrospector jackson = new JacksonAnnotationIntrospector(); - AnnotationIntrospector jaxb = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance()); + AnnotationIntrospector jaxb = new JaxbAnnotationIntrospector(); - this.mapper.setAnnotationIntrospector(new AnnotationIntrospectorPair(jackson, jaxb)); + this.mapper.setAnnotationIntrospector(new AnnotationIntrospector.Pair(jackson, jaxb)); // do not fail on unknown json properties - this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); } //~--- methods -------------------------------------------------------------- diff --git a/scm-webapp/src/main/resources/logback.default.xml b/scm-webapp/src/main/resources/logback.default.xml index bf18f02893..318cd6112a 100644 --- a/scm-webapp/src/main/resources/logback.default.xml +++ b/scm-webapp/src/main/resources/logback.default.xml @@ -90,8 +90,6 @@ - - diff --git a/scm-webapp/src/main/webapp/WEB-INF/web.xml b/scm-webapp/src/main/webapp/WEB-INF/web.xml index 8a54ee72cd..513c708e80 100644 --- a/scm-webapp/src/main/webapp/WEB-INF/web.xml +++ b/scm-webapp/src/main/webapp/WEB-INF/web.xml @@ -40,7 +40,7 @@ SCM-Manager ${project.version} - sonia.scm.boot.BootstrapContextListener + sonia.scm.boot.BootstrapListener @@ -48,45 +48,15 @@ - BootstrapFilter - sonia.scm.boot.BootstrapContextFilter + guiceFilter + sonia.scm.boot.BootstrapFilter - BootstrapFilter + guiceFilter /* - - - - resteasy.servlet.mapping.prefix - /api/rest - - - - Resteasy - - org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher - - - - - Resteasy - /api/rest/* - - - - - - - sonia.scm.HttpSessionListenerHolder - - - - index.html diff --git a/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js b/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js index 3d044d69c5..b1c0a5372f 100644 --- a/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js +++ b/scm-webapp/src/main/webapp/resources/js/action/sonia.action.changepasswordwindow.js @@ -55,7 +55,7 @@ Sonia.action.ChangePasswordWindow = Ext.extend(Ext.Window,{ title: this.titleText, items: [{ id: 'changePasswordForm', - url: restUrl + 'action/change-password', + url: restUrl + 'action/change-password.json', frame: true, xtype: 'form', monitorValid: true, diff --git a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js index 0f9c2fdd57..a985688a3e 100644 --- a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js @@ -261,7 +261,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ onSubmit: function(values){ this.el.mask(this.submitText); Ext.Ajax.request({ - url: restUrl + 'config', + url: restUrl + 'config.json', method: 'POST', jsonData: values, scope: this, @@ -283,7 +283,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{ onLoad: function(el){ var tid = setTimeout( function(){ el.mask(this.loadingText); }, 100); Ext.Ajax.request({ - url: restUrl + 'config', + url: restUrl + 'config.json', method: 'GET', scope: this, disableCaching: true, diff --git a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.formpanel.js b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.formpanel.js index 4ec278bf6b..5d560d9717 100644 --- a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.formpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.formpanel.js @@ -59,7 +59,7 @@ Sonia.group.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ // this.updateMembers(group); this.fireEvent('preUpdate', group); - var url = restUrl + 'groups/' + encodeURIComponent(group.name); + var url = restUrl + 'groups/' + encodeURIComponent(group.name) + '.json'; var el = this.el; var tid = setTimeout( function(){el.mask('Loading ...');}, 100); @@ -96,7 +96,7 @@ Sonia.group.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ } item.type = state.defaultUserType; - var url = restUrl + 'groups'; + var url = restUrl + 'groups.json'; var el = this.el; var tid = setTimeout( function(){el.mask('Loading ...');}, 100); diff --git a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js index 1bc3fbe819..18d3841fc2 100644 --- a/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js +++ b/scm-webapp/src/main/webapp/resources/js/group/sonia.group.panel.js @@ -95,7 +95,7 @@ Sonia.group.Panel = Ext.extend(Sonia.rest.Panel, { var selected = grid.getSelectionModel().getSelected(); if ( selected ){ var item = selected.data; - var url = restUrl + 'groups/' + encodeURIComponent(item.name); + var url = restUrl + 'groups/' + encodeURIComponent(item.name) + '.json'; Ext.MessageBox.show({ title: this.removeTitleText, diff --git a/scm-webapp/src/main/webapp/resources/js/login/sonia.login.form.js b/scm-webapp/src/main/webapp/resources/js/login/sonia.login.form.js index 19ad6d0e15..b27f2484b4 100644 --- a/scm-webapp/src/main/webapp/resources/js/login/sonia.login.form.js +++ b/scm-webapp/src/main/webapp/resources/js/login/sonia.login.form.js @@ -41,6 +41,7 @@ Sonia.login.Form = Ext.extend(Ext.FormPanel,{ failedDescriptionText: 'Incorrect username, password or not enough permission. Please Try again.', accountLockedText: 'Account is locked.', accountTemporaryLockedText: 'Account is temporary locked. Please try again later.', + rememberMeText: 'Remember me', initComponent: function(){ var buttons = []; @@ -93,14 +94,11 @@ Sonia.login.Form = Ext.extend(Ext.FormPanel,{ scope: this } } - }, { - name: 'grant_type', - value: 'password', - xtype: 'hidden' - }, { - name: 'cookie', - value: 'true', - xtype: 'hidden' + },{ + xtype: 'checkbox', + fieldLabel: this.rememberMeText, + name: 'rememberMe', + inputValue: 'true' }], buttons: buttons }; @@ -118,7 +116,6 @@ Sonia.login.Form = Ext.extend(Ext.FormPanel,{ authenticate: function(){ var form = this.getForm(); - form.submit({ scope: this, method: 'POST', diff --git a/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.center.js b/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.center.js index ebd2119886..11113e2601 100644 --- a/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.center.js +++ b/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.center.js @@ -81,7 +81,7 @@ Sonia.plugin.Center = Ext.extend(Ext.util.Observable, { var loadingBox = this.createLoadingBox( this.installWaitMsgText ); Ext.Ajax.request({ - url: restUrl + 'plugins/install/' + pluginId, + url: restUrl + 'plugins/install/' + pluginId + '.json', method: 'POST', scope: this, timeout: 300000, // 5min @@ -116,7 +116,7 @@ Sonia.plugin.Center = Ext.extend(Ext.util.Observable, { var loadingBox = this.createLoadingBox( this.uninstallWaitMsgText ); Ext.Ajax.request({ - url: restUrl + 'plugins/uninstall/' + pluginId, + url: restUrl + 'plugins/uninstall/' + pluginId + '.json', method: 'POST', scope: this, success: function(){ @@ -150,7 +150,7 @@ Sonia.plugin.Center = Ext.extend(Ext.util.Observable, { var loadingBox = this.createLoadingBox( this.updateWaitMsgText ); Ext.Ajax.request({ - url: restUrl + 'plugins/update/' + pluginId, + url: restUrl + 'plugins/update/' + pluginId + '.json', method: 'POST', scope: this, timeout: 300000, // 5min diff --git a/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.grid.js b/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.grid.js index 5f44e51ebc..cb5ea6bec1 100644 --- a/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/plugin/sonia.plugin.grid.js @@ -81,7 +81,7 @@ Sonia.plugin.Grid = Ext.extend(Sonia.rest.Grid, { var pluginStore = new Ext.data.GroupingStore({ proxy: new Ext.data.HttpProxy({ - url: restUrl + 'plugins/overview', + url: restUrl + 'plugins/overview.json', disableCaching: false }), reader: new Ext.data.JsonReader({ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.branchcombobox.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.branchcombobox.js index 4c3dcbc7c8..cddcad4552 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.branchcombobox.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.branchcombobox.js @@ -38,7 +38,7 @@ Sonia.repository.BranchComboBox = Ext.extend(Ext.form.ComboBox, { initComponent: function(){ var branchStore = new Sonia.rest.JsonStore({ proxy: new Ext.data.HttpProxy({ - url: restUrl + 'repositories/' + this.repositoryId + '/branches', + url: restUrl + 'repositories/' + this.repositoryId + '/branches.json', method: 'GET', disableCaching: false }), diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js index 468b99dbec..aa18d29e0d 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.changesetviewerpanel.js @@ -46,7 +46,7 @@ Sonia.repository.ChangesetViewerPanel = Ext.extend(Ext.Panel, { initComponent: function(){ if (! this.url){ - this.url = restUrl + 'repositories/' + this.repository.id + '/changesets'; + this.url = restUrl + 'repositories/' + this.repository.id + '/changesets.json'; } if ( ! this.startLimit ){ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.commitpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.commitpanel.js index 591d77d43f..7b72c4fca3 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.commitpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.commitpanel.js @@ -131,7 +131,7 @@ Sonia.repository.CommitPanel = Ext.extend(Ext.Panel, { } Ext.Ajax.request({ - url: restUrl + 'repositories/' + this.repository.id + '/changeset/' + this.revision, + url: restUrl + 'repositories/' + this.repository.id + '/changeset/' + this.revision + '.json', method: 'GET', scope: this, success: function(response){ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.formpanel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.formpanel.js index 422a81ce6b..66482399ac 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.formpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.formpanel.js @@ -73,7 +73,7 @@ Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ if ( debug ){ console.debug( 'update repository: ' + item.name ); } - var url = restUrl + 'repositories/' + item.id; + var url = restUrl + 'repositories/' + item.id + '.json'; var el = this.el; var tid = setTimeout( function(){el.mask('Loading ...');}, 100); @@ -124,7 +124,7 @@ Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ if ( debug ){ console.debug( 'create repository: ' + item.name ); } - var url = restUrl + 'repositories'; + var url = restUrl + 'repositories.json'; var el = this.el; var tid = setTimeout( function(){el.mask('Loading ...');}, 100); diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index 9e2f76f607..fb66b91a5a 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -71,7 +71,7 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { var repositoryStore = new Ext.data.GroupingStore({ proxy: new Ext.data.HttpProxy({ - url: restUrl + 'repositories', + url: restUrl + 'repositories.json', disableCaching: false }), idProperty: 'id', diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js index 076f73e712..195d7d7509 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js @@ -75,7 +75,7 @@ Sonia.repository.HealthCheckFailure = Ext.extend(Ext.Panel, { }, rerunHealthChecks: function(){ - var url = restUrl + 'repositories/' + this.repository.id + '/healthcheck'; + var url = restUrl + 'repositories/' + this.repository.id + '/healthcheck.json'; var el = this.el; var tid = setTimeout( function(){el.mask('Loading ...');}, 100); diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.importwindow.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.importwindow.js index ac6bbc2206..209b554e82 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.importwindow.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.importwindow.js @@ -514,7 +514,7 @@ Sonia.repository.ImportPanel = Ext.extend(Ext.Panel, { importFromUrl: function(layout, repository){ var lbox = this.showLoadingBox(); Ext.Ajax.request({ - url: restUrl + 'import/repositories/' + this.repositoryType + '/url', + url: restUrl + 'import/repositories/' + this.repositoryType + '/url.json', method: 'POST', scope: this, timeout: 300000, // 5min @@ -533,7 +533,7 @@ Sonia.repository.ImportPanel = Ext.extend(Ext.Panel, { importFromDirectory: function(layout){ var lbox = this.showLoadingBox(); Ext.Ajax.request({ - url: restUrl + 'import/repositories/' + this.repositoryType + '/directory', + url: restUrl + 'import/repositories/' + this.repositoryType + '/directory.json', timeout: 300000, // 5min method: 'POST', scope: this, diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.js index e978c0ffe9..7e10a58f4e 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.js @@ -181,7 +181,7 @@ Sonia.repository.get = function(id, callback){ execCallback(repository); } else { Ext.Ajax.request({ - url: restUrl + 'repositories/' + id, + url: restUrl + 'repositories/' + id + '.json', method: 'GET', scope: this, success: function(response){ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js index 767c294242..17a301509a 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.panel.js @@ -311,7 +311,7 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { console.debug('toggle repository ' + item.name + ' archive to ' + item.archived); } - var url = restUrl + 'repositories/' + item.id; + var url = restUrl + 'repositories/' + item.id + '.json'; this.executeRemoteCall(title, String.format(msg, item.name), 'PUT', url, item, function(result){ main.handleFailure( @@ -331,7 +331,7 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, { console.debug( 'remove repository ' + item.name ); } - var url = restUrl + 'repositories/' + item.id; + var url = restUrl + 'repositories/' + item.id + '.json'; this.executeRemoteCall(this.removeTitleText, String.format(this.removeMsgText, item.name), 'DELETE', url, null, function(result){ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js index 59677cab7e..489dd3c06c 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.repositorybrowser.js @@ -58,7 +58,7 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, { var browserStore = new Sonia.rest.JsonStore({ proxy: new Ext.data.HttpProxy({ - url: restUrl + 'repositories/' + this.repository.id, + url: restUrl + 'repositories/' + this.repository.id + '/browse.json', method: 'GET' }), fields: ['path', 'name', 'length', 'lastModified', 'directory', 'description', 'subrepository'], diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.tagcombobox.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.tagcombobox.js index 5af3cc97f1..3f045a8cf6 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.tagcombobox.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.tagcombobox.js @@ -37,7 +37,7 @@ Sonia.repository.TagComboBox = Ext.extend(Ext.form.ComboBox, { initComponent: function(){ var tagStore = new Sonia.rest.JsonStore({ proxy: new Ext.data.HttpProxy({ - url: restUrl + 'repositories/' + this.repositoryId + '/tags', + url: restUrl + 'repositories/' + this.repositoryId + '/tags.json', method: 'GET', disableCaching: false }), diff --git a/scm-webapp/src/main/webapp/resources/js/security/sonia.security.permissionspanel.js b/scm-webapp/src/main/webapp/resources/js/security/sonia.security.permissionspanel.js index 676114fc78..5ea8855251 100644 --- a/scm-webapp/src/main/webapp/resources/js/security/sonia.security.permissionspanel.js +++ b/scm-webapp/src/main/webapp/resources/js/security/sonia.security.permissionspanel.js @@ -53,7 +53,7 @@ Sonia.security.PermissionsPanel = Ext.extend(Ext.Panel, { this.permissionStore = new Sonia.rest.JsonStore({ proxy: new Ext.data.HttpProxy({ api: { - read: restUrl + this.baseUrl + read: restUrl + this.baseUrl + '.json' }, disableCaching: false }), @@ -179,7 +179,7 @@ Sonia.security.PermissionsPanel = Ext.extend(Ext.Panel, { addPermission: function(record){ Ext.Ajax.request({ - url: restUrl + this.baseUrl, + url: restUrl + this.baseUrl + '.json', method: 'POST', jsonData: record.data, scope: this, @@ -194,7 +194,7 @@ Sonia.security.PermissionsPanel = Ext.extend(Ext.Panel, { modifyPermission: function(id, record){ Ext.Ajax.request({ - url: restUrl + this.baseUrl + '/' + encodeURIComponent(id), + url: restUrl + this.baseUrl + '/' + encodeURIComponent(id) + '.json', method: 'PUT', jsonData: record.data, scope: this, @@ -207,7 +207,7 @@ Sonia.security.PermissionsPanel = Ext.extend(Ext.Panel, { removePermission: function(store, record){ Ext.Ajax.request({ - url: restUrl + this.baseUrl + '/' + encodeURIComponent(record.get('id')), + url: restUrl + this.baseUrl + '/' + encodeURIComponent(record.get('id')) + '.json', method: 'DELETE', scope: this, success: function(){ diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.global.js b/scm-webapp/src/main/webapp/resources/js/sonia.global.js index 98299546b1..a43feb824b 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.global.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.global.js @@ -83,7 +83,7 @@ var userSearchStore = new Ext.data.JsonStore({ idProperty: 'value', fields: ['value','label'], proxy: new Ext.data.HttpProxy({ - url: restUrl + 'search/users', + url: restUrl + 'search/users.json', method: 'GET' }) }); @@ -93,7 +93,7 @@ var groupSearchStore = new Ext.data.JsonStore({ idProperty: 'value', fields: ['value','label'], proxy: new Ext.data.HttpProxy({ - url: restUrl + 'search/groups', + url: restUrl + 'search/groups.json', method: 'GET' }) }); diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.scm.js b/scm-webapp/src/main/webapp/resources/js/sonia.scm.js index db92a77d60..6d7e6a3257 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.scm.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.scm.js @@ -689,4 +689,4 @@ Ext.onReady(function(){ main.init(); main.checkLogin(); -}); +}); \ No newline at end of file diff --git a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js index e8a03e5966..6ef00e73d7 100644 --- a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js @@ -129,7 +129,7 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ console.debug( 'update user: ' + item.name ); } this.fixRequest(item); - var url = restUrl + 'users/' + encodeURIComponent(item.name); + var url = restUrl + 'users/' + encodeURIComponent(item.name) + '.json'; Ext.Ajax.request({ url: url, jsonData: item, @@ -159,7 +159,7 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ this.fixRequest(user); // set user type user.type = state.defaultUserType; - var url = restUrl + 'users'; + var url = restUrl + 'users.json'; Ext.Ajax.request({ url: url, jsonData: user, diff --git a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js index b671e67bdc..c44d336ba9 100644 --- a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js @@ -49,7 +49,7 @@ Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, { var userStore = new Sonia.rest.JsonStore({ proxy: new Ext.data.HttpProxy({ - url: restUrl + 'users', + url: restUrl + 'users.json', disableCaching: false }), idProperty: 'name', diff --git a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js index 0ca0fd78e1..8e98c645df 100644 --- a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js +++ b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js @@ -126,7 +126,7 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, { var selected = grid.getSelectionModel().getSelected(); if ( selected ){ var item = selected.data; - var url = restUrl + 'users/' + encodeURIComponent(item.name); + var url = restUrl + 'users/' + encodeURIComponent(item.name) + '.json'; Ext.MessageBox.show({ title: this.removeTitleText, diff --git a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java index 33e020f85d..f8adb90ff1 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/GitLfsITCase.java @@ -32,9 +32,6 @@ package sonia.scm.it; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.TypeFactory; -import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; import com.google.common.base.Charsets; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.UniformInterfaceException; @@ -44,6 +41,8 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import org.apache.shiro.crypto.hash.Sha256Hash; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Test; @@ -82,7 +81,7 @@ public class GitLfsITCase { private Repository repository; public GitLfsITCase() { - mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(TypeFactory.defaultInstance())); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); } // lifecycle methods