diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgHookCallback.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgHookCallback.java index b970b08648..ed872a3f3e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgHookCallback.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/rest/resources/HgHookCallback.java @@ -40,6 +40,7 @@ import com.google.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.HgRepositoryHookEvent; import sonia.scm.repository.RepositoryManager; @@ -47,10 +48,10 @@ import sonia.scm.repository.RepositoryNotFoundException; //~--- JDK imports ------------------------------------------------------------ -import javax.ws.rs.GET; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; /** @@ -73,13 +74,15 @@ public class HgHookCallback * * @param repositoryManager * @param handler + * @param hookManager */ @Inject public HgHookCallback(RepositoryManager repositoryManager, - HgRepositoryHandler handler) + HgRepositoryHandler handler, HgHookManager hookManager) { this.repositoryManager = repositoryManager; this.handler = handler; + this.hookManager = hookManager; } //~--- methods -------------------------------------------------------------- @@ -91,38 +94,52 @@ public class HgHookCallback * * @param repositoryName * @param type + * @param challenge * @param node * * @return */ - @GET + @POST public Response hookCallback(@PathParam("repository") String repositoryName, @PathParam("type") String type, - @QueryParam("node") String node) + @FormParam("challenge") String challenge, + @FormParam("node") String node) { Response response = null; - try + if (hookManager.isAcceptAble(challenge)) { - repositoryManager.fireHookEvent(HgRepositoryHandler.TYPE_NAME, - repositoryName, - new HgRepositoryHookEvent(handler, - repositoryName, node)); - response = Response.ok().build(); - } - catch (RepositoryNotFoundException ex) - { - if (logger.isErrorEnabled()) + try { - logger.error("could not find repository {}", repositoryName); - - if (logger.isTraceEnabled()) + repositoryManager.fireHookEvent(HgRepositoryHandler.TYPE_NAME, + repositoryName, + new HgRepositoryHookEvent(handler, + repositoryName, node)); + response = Response.ok().build(); + } + catch (RepositoryNotFoundException ex) + { + if (logger.isErrorEnabled()) { - logger.trace("repository not found", ex); + logger.error("could not find repository {}", repositoryName); + + if (logger.isTraceEnabled()) + { + logger.trace("repository not found", ex); + } } + + response = Response.status(Response.Status.NOT_FOUND).build(); + } + } + else + { + if (logger.isWarnEnabled()) + { + logger.warn("hg hook challenge is not accept able"); } - response = Response.status(Response.Status.NOT_FOUND).build(); + response = Response.status(Response.Status.BAD_REQUEST).build(); } return response; @@ -133,6 +150,9 @@ public class HgHookCallback /** Field description */ private HgRepositoryHandler handler; + /** Field description */ + private HgHookManager hookManager; + /** Field description */ private RepositoryManager repositoryManager; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java new file mode 100644 index 0000000000..1f53c98f8f --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Singleton; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.UUID; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class HgHookManager +{ + + /** + * Method description + * + * + * @return + */ + public String getChallenge() + { + return challenge; + } + + /** + * Method description + * + * + * @param challenge + * + * @return + */ + public boolean isAcceptAble(String challenge) + { + return challenge.equals(challenge); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String challenge = UUID.randomUUID().toString(); +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookScriptFilter.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookScriptFilter.java index 9047c0a2e4..e340e1a952 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookScriptFilter.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookScriptFilter.java @@ -45,6 +45,7 @@ import sonia.scm.SCMContextProvider; import sonia.scm.io.RegexResourceProcessor; import sonia.scm.io.ResourceProcessor; import sonia.scm.repository.HgConfig; +import sonia.scm.repository.HgHookManager; import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.util.IOUtil; import sonia.scm.util.Util; @@ -86,13 +87,16 @@ public class HgHookScriptFilter extends HttpFilter * * @param context * @param handler + * @param hookManager */ @Inject public HgHookScriptFilter(SCMContextProvider context, - HgRepositoryHandler handler) + HgRepositoryHandler handler, + HgHookManager hookManager) { this.context = context; this.handler = handler; + this.hookManager = hookManager; } //~--- methods -------------------------------------------------------------- @@ -183,6 +187,7 @@ public class HgHookScriptFilter extends HttpFilter rp.addVariable("python", config.getPythonBinary()); rp.addVariable("path", Util.nonNull(config.getPythonPath())); rp.addVariable("url", url); + rp.addVariable("challenge", hookManager.getChallenge()); rp.process(input, output); script.setExecutable(true); } @@ -201,6 +206,9 @@ public class HgHookScriptFilter extends HttpFilter /** Field description */ private HgRepositoryHandler handler; + /** Field description */ + private HgHookManager hookManager; + /** Field description */ private volatile boolean written = false; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java index 6385ada2dc..1c003eb6b9 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgServletModule.java @@ -38,6 +38,7 @@ package sonia.scm.web; import com.google.inject.servlet.ServletModule; import sonia.scm.plugin.ext.Extension; +import sonia.scm.repository.HgHookManager; import sonia.scm.web.filter.BasicAuthenticationFilter; /** @@ -63,6 +64,7 @@ public class HgServletModule extends ServletModule @Override protected void configureServlets() { + bind(HgHookManager.class); // write hook script filter(MAPPING_ALL).through(HgHookScriptFilter.class); diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py index 0bb39e7f94..7e45c39298 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py @@ -17,11 +17,13 @@ if len(pythonPath) > 0: sys.path.insert(i, pathParts[i]) baseUrl = "${url}" +challenge = "${challenge}" def callback(ui, repo, hooktype, node=None, source=None, **kwargs): if node != None: - url = baseUrl + os.path.basename(repo.root) + "/" + hooktype + "?node=" + node - conn = urllib.urlopen(url); + url = baseUrl + os.path.basename(repo.root) + "/" + hooktype + data = urllib.urlencode({'node': node, 'challenge': challenge}) + conn = urllib.urlopen(url, data); if conn.code == 200: print( "scm-hook executed successfully" ) else: