diff --git a/pom.xml b/pom.xml index 0ff3c26906..23ea8daf86 100644 --- a/pom.xml +++ b/pom.xml @@ -274,7 +274,7 @@ false true - release,APIviz,doc + release,APIviz,doc,nativepkg @{project.version} true @@ -459,8 +459,8 @@ 1.2.3 - 3.3.2.201404171909-r - 1.8.5-scm1 + 3.4.1.201406201815-r + 1.8.5-scm2 16.0.1 diff --git a/scm-clients/scm-cli-client/pom.xml b/scm-clients/scm-cli-client/pom.xml index 44cb8e0d20..50b3c03c9d 100644 --- a/scm-clients/scm-cli-client/pom.xml +++ b/scm-clients/scm-cli-client/pom.xml @@ -1,54 +1,54 @@ - + 4.0.0 - + scm-clients sonia.scm.clients 2.0.0-SNAPSHOT - + sonia.scm.clients scm-cli-client 2.0.0-SNAPSHOT scm-cli-client - + - + javax.servlet servlet-api ${servlet.version} - - + + javax.transaction jta 1.1 provided - + sonia.scm.clients scm-client-impl 2.0.0-SNAPSHOT - + args4j args4j - 2.0.26 + 2.0.28 - + ch.qos.logback logback-classic ${logback.version} - + org.freemarker freemarker @@ -56,10 +56,10 @@ - + - + com.mycila.maven-license-plugin maven-license-plugin @@ -78,7 +78,7 @@ true - + org.apache.maven.plugins maven-assembly-plugin @@ -102,18 +102,18 @@ - + - + - + it - + - + org.apache.maven.plugins maven-dependency-plugin @@ -139,7 +139,7 @@ - + org.apache.maven.plugins maven-failsafe-plugin @@ -164,7 +164,7 @@ - + org.mortbay.jetty jetty-maven-plugin @@ -216,22 +216,22 @@ - + - + - - + + - + maven.jenkins-ci.org jenkins release repository http://maven.jenkins-ci.org/content/repositories/releases/ - + - + diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/EncryptSubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/EncryptSubCommand.java new file mode 100644 index 0000000000..af76698062 --- /dev/null +++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/EncryptSubCommand.java @@ -0,0 +1,98 @@ +/** + * 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.cli.cmd; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.kohsuke.args4j.Argument; + +/** + * + * @author Sebastian Sdorra + * @since 1.41 + */ +@Command( + name = "encrypt", + usage = "usageEncrypt", + group = "security" +) +public class EncryptSubCommand extends SubCommand +{ + + /** + * Method description + * + * + * @return + */ + public String getValue() + { + return value; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param value + */ + public void setValue(String value) + { + this.value = value; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + @Override + protected void run() + { + String enc = createSession().getSecurityHandler().encrypt(value); + + output.println(enc); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @Argument( + usage = "optionEncryptValue", + metaVar = "value", + required = true + ) + private String value; +} diff --git a/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GenerateKeySubCommand.java b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GenerateKeySubCommand.java new file mode 100644 index 0000000000..b8658391b0 --- /dev/null +++ b/scm-clients/scm-cli-client/src/main/java/sonia/scm/cli/cmd/GenerateKeySubCommand.java @@ -0,0 +1,55 @@ +/** + * 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.cli.cmd; + +/** + * + * @author Sebastian Sdorra + */ +@Command( + name = "generate-key", + usage = "usageGenerateKey", + group = "security" +) +public class GenerateKeySubCommand extends SubCommand +{ + + /** + * Method description + * + */ + @Override + protected void run() + { + output.println(createSession().getSecurityHandler().generateKey()); + } +} diff --git a/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand b/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand index 73e50f8940..b4d344adae 100644 --- a/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand +++ b/scm-clients/scm-cli-client/src/main/resources/META-INF/services/sonia.scm.cli.cmd.SubCommand @@ -60,6 +60,10 @@ sonia.scm.cli.cmd.ModifyGroupSubCommand sonia.scm.cli.cmd.AddMembersSubCommand sonia.scm.cli.cmd.DeleteMembersSubCommand +# security +sonia.scm.cli.cmd.EncryptSubCommand +sonia.scm.cli.cmd.GenerateKeySubCommand + # misc sonia.scm.cli.cmd.VersionSubCommand sonia.scm.cli.cmd.ServerVersionSubCommand diff --git a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties index d5c707f090..69d88b2cfe 100644 --- a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties +++ b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/i18n.properties @@ -68,6 +68,8 @@ optionGroupDescription = Description optionGroupType = Type optionGroupMember = Member +optionEncryptValue = value to encrypt + repositoryNotFound = The repository is not available userNotFound = The user could not be found groupNotFoun = The group could not be found @@ -85,6 +87,7 @@ misc = Miscellaneous repository = Repository group = Group user = User +security = Security level = Logging-Level boolean = true or false @@ -114,4 +117,7 @@ usageModifyUser = Modify a user usageModifyRepository = Modify a repository usageStoreConfig = Stores the current configuration usageVersion = Show the version of scm-cli-client -usageServerVersion = Show the version of the scm-manager \ No newline at end of file +usageServerVersion = Show the version of the scm-manager + +usageEncrypt = Encrypts the given value +usageGenerateKey = Generates a unique key \ No newline at end of file diff --git a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmClientSession.java b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmClientSession.java index 7e39258390..7f58a94852 100644 --- a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmClientSession.java +++ b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/ScmClientSession.java @@ -73,6 +73,14 @@ public interface ScmClientSession extends Closeable */ public RepositoryClientHandler getRepositoryHandler(); + /** + * Method description + * + * + * @return + */ + public SecurityClientHandler getSecurityHandler(); + /** * Method description * diff --git a/scm-clients/scm-client-api/src/main/java/sonia/scm/client/SecurityClientHandler.java b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/SecurityClientHandler.java new file mode 100644 index 0000000000..a0131a7f1c --- /dev/null +++ b/scm-clients/scm-client-api/src/main/java/sonia/scm/client/SecurityClientHandler.java @@ -0,0 +1,59 @@ +/** + * 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.client; + +/** + * + * @author Sebastian Sdorra + * @since 1.41 + */ +public interface SecurityClientHandler +{ + + /** + * Method description + * + * + * @param value + * + * @return + */ + public String encrypt(String value); + + /** + * Method description + * + * + * @return + */ + public String generateKey(); +} diff --git a/scm-clients/scm-client-impl/pom.xml b/scm-clients/scm-client-impl/pom.xml index e9c7551c7d..8bfe7af4a9 100644 --- a/scm-clients/scm-client-impl/pom.xml +++ b/scm-clients/scm-client-impl/pom.xml @@ -45,30 +45,6 @@ ${jersey.version} - - sonia.net.ahc - jersey-ahc-client - 1.0.2.1 - - - jaxb-api - javax.xml.bind - - - jaxb-impl - com.sun.xml.bind - - - stax-api - stax - - - jersey-json - com.sun.jersey - - - - @@ -101,7 +77,13 @@ Sonatype Sonatype Release - http://oss.sonatype.org/content/repositories/releases + http://oss.sonatype.org/content/repositories/releases + + + + maven.scm-manager.org + scm-manager release repository + http://maven.scm-manager.org/nexus/content/groups/public diff --git a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientProvider.java b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientProvider.java index 8c38f83eb1..48111de0d8 100644 --- a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientProvider.java +++ b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientProvider.java @@ -38,9 +38,6 @@ package sonia.scm.client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonatype.spice.jersey.client.ahc.AhcHttpClient; -import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig; - import sonia.scm.ScmState; import sonia.scm.url.UrlProvider; import sonia.scm.url.UrlProviderFactory; @@ -49,11 +46,20 @@ import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientHandlerException; +import com.sun.jersey.api.client.ClientRequest; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.filter.ClientFilter; import com.sun.jersey.core.util.MultivaluedMapImpl; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.NewCookie; /** * @@ -100,7 +106,7 @@ public class JerseyClientProvider implements ScmClientProvider */ @Override public JerseyClientSession createSession(String url, String username, - String password) + String password) { AssertUtil.assertIsNotEmpty(url); @@ -111,59 +117,24 @@ public class JerseyClientProvider implements ScmClientProvider user = username; } - if (logger.isInfoEnabled()) - { - logger.info("create new session for {} with username {}", url, user); - } + logger.info("create new session for {} with username {}", url, user); UrlProvider urlProvider = UrlProviderFactory.createUrlProvider(url, UrlProviderFactory.TYPE_RESTAPI_XML); - DefaultAhcConfig config = new DefaultAhcConfig(); - AhcHttpClient client = AhcHttpClient.create(config); - ClientResponse response = null; + + Client client = Client.create(); + + client.addFilter(new CookieClientFilter()); + + ClientResponse response; if (Util.isNotEmpty(username) && Util.isNotEmpty(password)) { - String authUrl = urlProvider.getAuthenticationUrl(); - - if (logger.isDebugEnabled()) - { - logger.debug("try login at {}", authUrl); - } - - WebResource resource = ClientUtil.createResource(client, authUrl, - enableLogging); - - if (logger.isDebugEnabled()) - { - logger.debug("try login for {}", username); - } - - MultivaluedMap formData = new MultivaluedMapImpl(); - - formData.add("username", username); - formData.add("password", password); - response = resource.type("application/x-www-form-urlencoded").post( - ClientResponse.class, formData); + response = login(urlProvider, client, username, password); } else { - String stateUrl = urlProvider.getStateUrl(); - - if (logger.isDebugEnabled()) - { - logger.debug("retrive state from {}", stateUrl); - } - - WebResource resource = ClientUtil.createResource(client, stateUrl, - enableLogging); - - if (logger.isDebugEnabled()) - { - logger.debug("try anonymous login"); - } - - response = resource.get(ClientResponse.class); + response = state(urlProvider, client); } ClientUtil.checkResponse(response); @@ -172,10 +143,7 @@ public class JerseyClientProvider implements ScmClientProvider if (!state.isSuccess()) { - if (logger.isWarnEnabled()) - { - logger.warn("server returned state failed"); - } + logger.warn("server returned state failed"); throw new ScmClientException("create ScmClientSession failed"); } @@ -187,6 +155,122 @@ public class JerseyClientProvider implements ScmClientProvider return new JerseyClientSession(client, urlProvider, state); } + /** + * Method description + * + * + * @param urlProvider + * @param client + * @param username + * @param password + * + * @return + */ + private ClientResponse login(UrlProvider urlProvider, Client client, + String username, String password) + { + String authUrl = urlProvider.getAuthenticationUrl(); + + if (logger.isDebugEnabled()) + { + logger.debug("try login at {}", authUrl); + } + + WebResource resource = ClientUtil.createResource(client, authUrl, + enableLogging); + + if (logger.isDebugEnabled()) + { + logger.debug("try login for {}", username); + } + + MultivaluedMap formData = new MultivaluedMapImpl(); + + formData.add("username", username); + formData.add("password", password); + + return resource.type("application/x-www-form-urlencoded").post( + ClientResponse.class, formData); + } + + /** + * Method description + * + * + * @param urlProvider + * @param client + * + * @return + */ + private ClientResponse state(UrlProvider urlProvider, Client client) + { + String stateUrl = urlProvider.getStateUrl(); + + if (logger.isDebugEnabled()) + { + logger.debug("retrive state from {}", stateUrl); + } + + WebResource resource = ClientUtil.createResource(client, stateUrl, + enableLogging); + + if (logger.isDebugEnabled()) + { + logger.debug("try anonymous login"); + } + + return resource.get(ClientResponse.class); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 14/07/05 + * @author Enter your name here... + */ + private class CookieClientFilter extends ClientFilter + { + + /** + * Method description + * + * + * @param request + * + * @return + * + * @throws ClientHandlerException + */ + @Override + public ClientResponse handle(ClientRequest request) + throws ClientHandlerException + { + for (NewCookie c : cookies) + { + request.getHeaders().putSingle("Cookie", c); + } + + ClientResponse response = getNext().handle(request); + + if (response.getCookies() != null) + { + cookies.addAll(response.getCookies()); + } + + return response; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private final List cookies = + Collections.synchronizedList(new ArrayList()); + } + + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientSession.java b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientSession.java index 7e662bc938..46eeb7d222 100644 --- a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientSession.java +++ b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseyClientSession.java @@ -67,7 +67,7 @@ public class JerseyClientSession implements ScmClientSession * @param state */ public JerseyClientSession(Client client, UrlProvider urlProvider, - ScmState state) + ScmState state) { this.client = client; this.urlProvider = urlProvider; @@ -129,6 +129,18 @@ public class JerseyClientSession implements ScmClientSession return new JerseyRepositoryClientHandler(this); } + /** + * Method description + * + * + * @return + */ + @Override + public SecurityClientHandler getSecurityHandler() + { + return new JerseySecurityClientHandler(this); + } + /** * Method description * diff --git a/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseySecurityClientHandler.java b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseySecurityClientHandler.java new file mode 100644 index 0000000000..5f24752078 --- /dev/null +++ b/scm-clients/scm-client-impl/src/main/java/sonia/scm/client/JerseySecurityClientHandler.java @@ -0,0 +1,90 @@ +/** + * 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.client; + +/** + * + * @author Sebastian Sdorra + */ +public class JerseySecurityClientHandler implements SecurityClientHandler +{ + + /** + * Constructs ... + * + * + * @param session + */ + JerseySecurityClientHandler(JerseyClientSession session) + { + this.session = session; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param value + * + * @return + */ + @Override + public String encrypt(String value) + { + String url = + session.getUrlProvider().getSecurityUrlProvider().getEncryptUrl(); + + return session.getClient().resource(url).post(String.class, value); + } + + /** + * Method description + * + * + * @return + */ + @Override + public String generateKey() + { + String url = + session.getUrlProvider().getSecurityUrlProvider().getGenerateKeyUrl(); + + return session.getClient().resource(url).get(String.class); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private final JerseyClientSession session; +} diff --git a/scm-core/src/main/java/sonia/scm/url/RestSecurityUrlProvider.java b/scm-core/src/main/java/sonia/scm/url/RestSecurityUrlProvider.java new file mode 100644 index 0000000000..513f728708 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/url/RestSecurityUrlProvider.java @@ -0,0 +1,95 @@ +/** + * 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.url; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.util.HttpUtil; + +/** + * + * @author Sebastian Sdorra + * @since 1.41 + */ +public class RestSecurityUrlProvider implements SecurityUrlProvider +{ + + /** Field description */ + private static final String PATH_ENCRYPT = "security/cipher/encrypt"; + + /** Field description */ + private static final String PATH_KEY = "security/key"; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param baseUrl + */ + public RestSecurityUrlProvider(String baseUrl) + { + this.baseUrl = baseUrl; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getEncryptUrl() + { + return HttpUtil.append(baseUrl, PATH_ENCRYPT); + } + + /** + * Method description + * + * + * @return + */ + @Override + public String getGenerateKeyUrl() + { + return HttpUtil.append(baseUrl, PATH_KEY); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private final String baseUrl; +} diff --git a/scm-core/src/main/java/sonia/scm/url/RestUrlProvider.java b/scm-core/src/main/java/sonia/scm/url/RestUrlProvider.java index 1d60f2a91b..cb0b3de82d 100644 --- a/scm-core/src/main/java/sonia/scm/url/RestUrlProvider.java +++ b/scm-core/src/main/java/sonia/scm/url/RestUrlProvider.java @@ -130,6 +130,18 @@ public class RestUrlProvider implements UrlProvider return new RestRepositoryUrlProvider(baseUrl, PART_REPOSITORIES, extension); } + /** + * Method description + * + * + * @return + */ + @Override + public SecurityUrlProvider getSecurityUrlProvider() + { + return new RestSecurityUrlProvider(baseUrl); + } + /** * Method description * diff --git a/scm-core/src/main/java/sonia/scm/url/SecurityUrlProvider.java b/scm-core/src/main/java/sonia/scm/url/SecurityUrlProvider.java new file mode 100644 index 0000000000..e000c9b754 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/url/SecurityUrlProvider.java @@ -0,0 +1,59 @@ +/** + * 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.url; + +/** + * + * @author Sebastian Sdorra + * @since 1.41 + */ +public interface SecurityUrlProvider +{ + + /** + * Method description + * + * + * @return + */ + public String getGenerateKeyUrl(); + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getEncryptUrl(); +} diff --git a/scm-core/src/main/java/sonia/scm/url/UrlProvider.java b/scm-core/src/main/java/sonia/scm/url/UrlProvider.java index 694ea1b698..e6c3e4911a 100644 --- a/scm-core/src/main/java/sonia/scm/url/UrlProvider.java +++ b/scm-core/src/main/java/sonia/scm/url/UrlProvider.java @@ -72,6 +72,16 @@ public interface UrlProvider */ public RepositoryUrlProvider getRepositoryUrlProvider(); + /** + * Method description + * + * + * @return + * + * @since 1.41 + */ + public SecurityUrlProvider getSecurityUrlProvider(); + /** * Method description * diff --git a/scm-core/src/main/java/sonia/scm/url/WUIUrlProvider.java b/scm-core/src/main/java/sonia/scm/url/WUIUrlProvider.java index 0c92fcb406..e6a8388e0d 100644 --- a/scm-core/src/main/java/sonia/scm/url/WUIUrlProvider.java +++ b/scm-core/src/main/java/sonia/scm/url/WUIUrlProvider.java @@ -124,6 +124,19 @@ public class WUIUrlProvider implements UrlProvider return new WUIRepositoryUrlProvider(baseUrl, COMPONENT_REPOSITORY); } + /** + * Method description + * + * + * @return + */ + @Override + public SecurityUrlProvider getSecurityUrlProvider() + { + throw new UnsupportedOperationException( + "this provider does not support security url provider."); + } + /** * Returns the baseUrl, because there is no state url. * diff --git a/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/footer.html b/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/footer.html index a235efd5d9..d511f70a38 100644 --- a/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/footer.html +++ b/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/footer.html @@ -8,7 +8,7 @@

Links

  • - Download + Download
  • Issue Tracker @@ -37,22 +37,33 @@

    Social

@@ -84,8 +95,8 @@ - - + + diff --git a/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/header.html b/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/header.html index 094f5a659b..a1817abde0 100644 --- a/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/header.html +++ b/scm-plugin-backend/src/main/webapp/WEB-INF/ftl/template/header.html @@ -38,13 +38,13 @@ SCM-Manager Plugin-Backend - + - - - + + + @@ -88,22 +88,22 @@ diff --git a/scm-plugins/scm-hg-plugin/pom.xml b/scm-plugins/scm-hg-plugin/pom.xml index a790b69756..37542b1403 100644 --- a/scm-plugins/scm-hg-plugin/pom.xml +++ b/scm-plugins/scm-hg-plugin/pom.xml @@ -25,6 +25,15 @@ 0.8-SNAPSHOT
+ + + + sonia.scm + scm-test + 2.0.0-SNAPSHOT + test + + diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java index b568cde7ee..dc0ab774dc 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java @@ -41,6 +41,7 @@ import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.tmatesoft.svn.core.ISVNLogEntryHandler; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.io.SVNRepository; @@ -115,21 +116,16 @@ public class SvnLogCommand extends AbstractSvnCommand implements LogCommand try { - long revisioNumber = Long.parseLong(revision); - SVNRepository repository = open(); - Collection entries = repository.log(null, null, - revisioNumber, revisioNumber, true, - true); + long revisioNumber = parseRevision(revision); + SVNRepository repo = open(); + Collection entries = repo.log(null, null, revisioNumber, + revisioNumber, true, true); if (Util.isNotEmpty(entries)) { changeset = SvnUtil.createChangeset(entries.iterator().next()); } } - catch (NumberFormatException ex) - { - throw new RepositoryException("could not convert revision", ex); - } catch (SVNException ex) { throw new RepositoryException("could not open repository", ex); @@ -160,75 +156,30 @@ public class SvnLogCommand extends AbstractSvnCommand implements LogCommand } ChangesetPagingResult changesets = null; - String startRevision = request.getStartChangeset(); - String endRevision = request.getEndChangeset(); + int start = request.getPagingStart(); + int limit = request.getPagingLimit(); + long startRevision = parseRevision(request.getStartChangeset()); + long endRevision = parseRevision(request.getEndChangeset()); + String[] pathArray = null; + + if (!Strings.isNullOrEmpty(request.getPath())) + { + pathArray = new String[] { request.getPath() }; + } try { - SVNRepository repository = open(); - long startRev = repository.getLatestRevision(); - long endRev = 0; - long maxRev = startRev; + SVNRepository repo = open(); - if (!Strings.isNullOrEmpty(startRevision)) + if ((startRevision > 0) || (pathArray != null)) { - startRev = Long.parseLong(startRevision); + changesets = getChangesets(repo, startRevision, endRevision, start, + limit, pathArray); } - - if (!Strings.isNullOrEmpty(endRevision)) + else { - endRev = Long.parseLong(endRevision); + changesets = getChangesets(repo, start, limit); } - - String[] pathArray = null; - - if (!Strings.isNullOrEmpty(request.getPath())) - { - pathArray = new String[] { request.getPath() }; - } - - List changesetList = Lists.newArrayList(); - Collection entries = repository.log(pathArray, null, - startRev, endRev, true, true); - - for (SVNLogEntry entry : entries) - { - if (entry.getRevision() <= maxRev) - { - changesetList.add(entry); - } - } - - int total = changesetList.size(); - int start = request.getPagingStart(); - int max = request.getPagingLimit() + start; - int end = total; - - if ((max > 0) && (end > max)) - { - end = max; - } - - if (start < 0) - { - start = 0; - } - - if (logger.isTraceEnabled()) - { - logger.trace( - "create sublist from {} to {} of total {} collected changesets", - start, end, total); - } - - changesetList = changesetList.subList(start, end); - changesets = new ChangesetPagingResult(total, - SvnUtil.createChangesets(changesetList)); - } - catch (NumberFormatException ex) - { - throw new RepositoryException( - "could not parse revision ".concat(startRevision), ex); } catch (SVNException ex) { @@ -237,4 +188,184 @@ public class SvnLogCommand extends AbstractSvnCommand implements LogCommand return changesets; } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param v + * + * @return + * + * @throws RepositoryException + */ + private long parseRevision(String v) throws RepositoryException + { + long result = -1l; + + if (!Strings.isNullOrEmpty(v)) + { + try + { + result = Long.parseLong(v); + } + catch (NumberFormatException ex) + { + throw new RepositoryException( + String.format("could not convert revision %s", v), ex); + } + } + + return result; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param repo + * @param start + * @param limit + * + * @return + * + * @throws SVNException + */ + private ChangesetPagingResult getChangesets(SVNRepository repo, int start, + int limit) + throws SVNException + { + long latest = repo.getLatestRevision(); + long startRev = latest - start; + long endRev = Math.max(startRev - (limit - 1), 0); + + final List changesets = Lists.newArrayList(); + + if (startRev > 0) + { + logger.debug("fetch changeset from {} to {}", startRev, endRev); + repo.log(null, startRev, endRev, true, true, + new ChangesetCollector(changesets)); + } + + return new ChangesetPagingResult((int) (latest + 1l), changesets); + } + + /** + * Method description + * + * + * @param repo + * @param startRevision + * @param endRevision + * @param start + * @param limit + * @param path + * + * @return + * + * @throws SVNException + */ + private ChangesetPagingResult getChangesets(SVNRepository repo, + long startRevision, long endRevision, int start, int limit, String[] path) + throws SVNException + { + long startRev; + long endRev = Math.max(endRevision, 0); + long maxRev = repo.getLatestRevision(); + + if (startRevision >= 0l) + { + startRev = startRevision; + } + else + { + startRev = maxRev; + } + + List changesetList = Lists.newArrayList(); + + logger.debug("fetch changeset from {} to {} for path {}", startRev, endRev, + path); + + Collection entries = repo.log(path, null, startRev, endRev, + true, true); + + for (SVNLogEntry entry : entries) + { + if (entry.getRevision() <= maxRev) + { + changesetList.add(entry); + } + } + + int total = changesetList.size(); + int max = limit + start; + int end = total; + + if ((max > 0) && (end > max)) + { + end = max; + } + + if (start < 0) + { + start = 0; + } + + logger.trace( + "create sublist from {} to {} of total {} collected changesets", start, + end, total); + + changesetList = changesetList.subList(start, end); + + return new ChangesetPagingResult(total, + SvnUtil.createChangesets(changesetList)); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Collect and convert changesets. + * + */ + private static class ChangesetCollector implements ISVNLogEntryHandler + { + + /** + * Constructs ... + * + * + * @param changesets + */ + public ChangesetCollector(Collection changesets) + { + this.changesets = changesets; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param logEntry + * + * @throws SVNException + */ + @Override + public void handleLogEntry(SVNLogEntry logEntry) throws SVNException + { + changesets.add(SvnUtil.createChangeset(logEntry)); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private final Collection changesets; + } } diff --git a/scm-server/pom.xml b/scm-server/pom.xml index 6f6275145a..dd04797de3 100644 --- a/scm-server/pom.xml +++ b/scm-server/pom.xml @@ -2,7 +2,7 @@ 4.0.0 - + scm sonia.scm @@ -80,7 +80,7 @@ commons-daemon - + java.awt.headless=true @@ -167,18 +167,18 @@ scm-server - + nativepkg - + - + com.github.sdorra nativepkg-maven-plugin - 1.0.0-SNAPSHOT + 1.1.0 @@ -268,34 +268,44 @@ /opt/scm-server/lib ${exploded.directory}/lib + + /var/cache/scm + scm + scm + 0700 + false + /var/cache/scm/work scm scm 0700 + false /var/log/scm scm scm 0770 + false /var/lib/scm scm scm 0700 + false - + - + - + 1.0.15 ${project.build.directory}/appassembler/commons-daemon/scm-server diff --git a/scm-test/pom.xml b/scm-test/pom.xml index 6cc96ae68b..a839d36dde 100644 --- a/scm-test/pom.xml +++ b/scm-test/pom.xml @@ -49,7 +49,7 @@ - org.eclipse.jgit + sonia.jgit org.eclipse.jgit ${jgit.version} diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 492fbf8c7d..126c63e60f 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -55,7 +55,7 @@ scm-dao-xml 2.0.0-SNAPSHOT - + @@ -423,6 +423,7 @@ maven-war-plugin 2.2 + true ${project.build.directory}/dependency-rewrite @@ -506,7 +507,6 @@ - release diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index d091e39486..c0cb5a3a2e 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -55,6 +55,7 @@ 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; @@ -340,6 +341,9 @@ public class ScmServletModule extends JerseyServletModule 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); diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/CipherResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/CipherResource.java new file mode 100644 index 0000000000..27de46ce03 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/CipherResource.java @@ -0,0 +1,86 @@ +/** + * 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.api.rest.resources; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; + +import org.apache.shiro.SecurityUtils; + +import sonia.scm.security.CipherUtil; +import sonia.scm.security.Role; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * Rest resource to encrypt values. + * + * @author Sebastian Sdorra + * @since 1.41 + */ +@Path("security/cipher") +public class CipherResource +{ + + /** + * Encrypts the request body and returns an encrypted string. This method can + * only executed with administration privileges.
+ *
+ *
    + *
  • 200 success
  • + *
  • 500 internal server error
  • + *
+ * + * @param value value to encrypt + * + * @return unique key + */ + @POST + @Path("encrypt") + @Produces(MediaType.TEXT_PLAIN) + public String encrypt(String value) + { + SecurityUtils.getSubject().checkRole(Role.ADMIN); + + Preconditions.checkArgument(!Strings.isNullOrEmpty(value), + "value is required"); + + return CipherUtil.getInstance().encode(value); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/KeyResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/KeyResource.java new file mode 100644 index 0000000000..619a8e9a2a --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/KeyResource.java @@ -0,0 +1,98 @@ +/** + * 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.api.rest.resources; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; + +import org.apache.shiro.SecurityUtils; + +import sonia.scm.security.KeyGenerator; +import sonia.scm.security.Role; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * Rest resource to generate unique keys. + * + * @author Sebastian Sdorra + * @since 1.41 + */ +@Path("security/key") +public class KeyResource +{ + + /** + * Constructs a new KeyResource. + * + * + * @param keyGenerator key generator + */ + @Inject + public KeyResource(KeyGenerator keyGenerator) + { + this.keyGenerator = keyGenerator; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Generates a unique key. This method can only executed with administration + * privileges.
+ *
+ *
    + *
  • 200 success
  • + *
  • 500 internal server error
  • + *
+ * + * @return unique key + */ + @GET + @Produces(MediaType.TEXT_PLAIN) + public String generateKey() + { + SecurityUtils.getSubject().checkRole(Role.ADMIN); + + return keyGenerator.createKey(); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private final KeyGenerator keyGenerator; +} diff --git a/scm-webapp/src/main/java/sonia/scm/filter/MDCFilter.java b/scm-webapp/src/main/java/sonia/scm/filter/MDCFilter.java new file mode 100644 index 0000000000..6630543bc3 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/filter/MDCFilter.java @@ -0,0 +1,131 @@ +/** + * 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.filter; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Singleton; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; + +import org.slf4j.MDC; + +import sonia.scm.SCMContext; +import sonia.scm.web.filter.HttpFilter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class MDCFilter extends HttpFilter +{ + + /** Field description */ + private static final String MDC_CLIEN_HOST = "client_host"; + + /** Field description */ + private static final String MDC_CLIEN_IP = "client_ip"; + + /** Field description */ + private static final String MDC_USERNAME = "username"; + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param request + * @param response + * @param chain + * + * @throws IOException + * @throws ServletException + */ + @Override + protected void doFilter(HttpServletRequest request, + HttpServletResponse response, FilterChain chain) + throws IOException, ServletException + { + MDC.put(MDC_USERNAME, getUsername()); + MDC.put(MDC_CLIEN_IP, request.getRemoteAddr()); + MDC.put(MDC_CLIEN_HOST, request.getRemoteHost()); + + try + { + chain.doFilter(request, response); + } + finally + { + MDC.remove(MDC_USERNAME); + MDC.remove(MDC_CLIEN_IP); + MDC.remove(MDC_CLIEN_HOST); + } + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + private String getUsername() + { + Subject subject = SecurityUtils.getSubject(); + String username; + Object principal = subject.getPrincipal(); + + if (principal == null) + { + username = SCMContext.USER_ANONYMOUS; + } + else + { + username = principal.toString(); + } + + return username; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/AdvancedPluginConfiguration.java b/scm-webapp/src/main/java/sonia/scm/plugin/AdvancedPluginConfiguration.java new file mode 100644 index 0000000000..88cde5e14c --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/plugin/AdvancedPluginConfiguration.java @@ -0,0 +1,164 @@ +/** + * 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.plugin; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.ImmutableSet; + +import sonia.scm.xml.XmlCipherStringAdapter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Set; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +/** + * + * @author Sebastian Sdorra + * @since 1.41 + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "advanced-configuration") +public class AdvancedPluginConfiguration +{ + + /** + * Method description + * + * + * @return + */ + public Set getRepositories() + { + if (repositories == null) + { + repositories = ImmutableSet.of(); + } + + return repositories; + } + + /** + * Method description + * + * + * @return + */ + public Set getServers() + { + if (servers == null) + { + servers = ImmutableSet.of(); + } + + return servers; + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 14/07/20 + * @author Enter your name here... + */ + @XmlAccessorType(XmlAccessType.FIELD) + public static class Server + { + + /** + * Method description + * + * + * @return + */ + public String getId() + { + return id; + } + + /** + * Method description + * + * + * @return + */ + public String getPassword() + { + return password; + } + + /** + * Method description + * + * + * @return + */ + public String getUsername() + { + return username; + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private String id; + + /** Field description */ + @XmlJavaTypeAdapter(XmlCipherStringAdapter.class) + private String password; + + /** Field description */ + private String username; + } + + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlElement(name = "repository") + @XmlElementWrapper(name = "repositories") + private Set repositories; + + /** Field description */ + @XmlElement(name = "server") + @XmlElementWrapper(name = "servers") + private Set servers; +} diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java index d5638c340a..5da9070558 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java @@ -38,7 +38,6 @@ package sonia.scm.plugin; import com.github.legman.Subscribe; import com.google.common.base.Predicate; -import com.google.common.collect.Sets; import com.google.common.io.Files; import com.google.inject.Inject; import com.google.inject.Provider; @@ -48,7 +47,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.ConfigurationException; -import sonia.scm.SCMContext; import sonia.scm.SCMContextProvider; import sonia.scm.cache.Cache; import sonia.scm.cache.CacheManager; @@ -100,6 +98,10 @@ public class DefaultPluginManager implements PluginManager /** Field description */ public static final String ENCODING = "UTF-8"; + /** Field description */ + private static final String ADVANCED_CONFIGURATION = + "advanced-configuration.xml"; + /** the logger for DefaultPluginManager */ private static final Logger logger = LoggerFactory.getLogger(DefaultPluginManager.class); @@ -116,10 +118,6 @@ public class DefaultPluginManager implements PluginManager /** * Constructs ... * - * - * - * - * * @param context * @param configuration * @param pluginLoader @@ -647,7 +645,8 @@ public class DefaultPluginManager implements PluginManager /*if (pluginHandler == null) { pluginHandler = new AetherPluginHandler(this, - SCMContext.getContext(), configuration); + SCMContext.getContext(), configuration, + advancedPluginConfiguration); } pluginHandler.setPluginRepositories(center.getRepositories());*/ diff --git a/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java b/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java index 8dce05f083..76d4804218 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java +++ b/scm-webapp/src/main/java/sonia/scm/security/DefaultSecuritySystem.java @@ -36,8 +36,10 @@ package sonia.scm.security; //~--- non-JDK imports -------------------------------------------------------- import com.github.legman.Subscribe; +import com.google.common.base.Preconditions; import com.google.common.base.Predicate; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.inject.Inject; @@ -125,6 +127,7 @@ public class DefaultSecuritySystem implements SecuritySystem public StoredAssignedPermission addPermission(AssignedPermission permission) { assertIsAdmin(); + validatePermission(permission); String id = store.put(permission); @@ -234,6 +237,7 @@ public class DefaultSecuritySystem implements SecuritySystem public void modifyPermission(StoredAssignedPermission permission) { assertIsAdmin(); + validatePermission(permission); synchronized (store) { @@ -425,6 +429,20 @@ public class DefaultSecuritySystem implements SecuritySystem availablePermissions = builder.build(); } + /** + * Method description + * + * + * @param perm + */ + private void validatePermission(AssignedPermission perm) + { + Preconditions.checkArgument(!Strings.isNullOrEmpty(perm.getName()), + "name is required"); + Preconditions.checkArgument(!Strings.isNullOrEmpty(perm.getPermission()), + "permission is required"); + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionResolver.java b/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionResolver.java index 4ef83c1640..50517b03df 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionResolver.java +++ b/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionResolver.java @@ -36,6 +36,7 @@ package sonia.scm.security; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.base.Splitter; +import com.google.common.base.Strings; import org.apache.shiro.authz.permission.PermissionResolver; @@ -76,24 +77,33 @@ public class RepositoryPermissionResolver implements PermissionResolver public RepositoryPermission resolvePermission(String permissionString) { RepositoryPermission permission = null; - Iterator permissionIt = - Splitter.on(':').omitEmptyStrings().trimResults().split( - permissionString).iterator(); - if (permissionIt.hasNext()) + if (!Strings.isNullOrEmpty(permissionString)) { - String type = permissionIt.next(); + Iterator permissionIt = + Splitter.on(':').omitEmptyStrings().trimResults().split( + permissionString).iterator(); - if (type.equals(RepositoryPermission.TYPE)) + if (permissionIt.hasNext()) { - permission = createRepositoryPermission(permissionIt); - } - else if (logger.isWarnEnabled()) - { - logger.warn("permission '{}' is not a repository permission", - permissionString); + String type = permissionIt.next(); + + if (type.equals(RepositoryPermission.TYPE)) + { + permission = createRepositoryPermission(permissionIt); + } + else if (logger.isWarnEnabled()) + { + logger.warn("permission '{}' is not a repository permission", + permissionString); + } } } + else + { + logger.warn( + "permision string is empty, could not resolve empty permission"); + } return permission; } diff --git a/scm-webapp/src/main/resources/logback.default.xml b/scm-webapp/src/main/resources/logback.default.xml index c391760e14..da93761850 100644 --- a/scm-webapp/src/main/resources/logback.default.xml +++ b/scm-webapp/src/main/resources/logback.default.xml @@ -61,7 +61,9 @@ - + + +