mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-01 19:15:52 +01:00
prompt authentication again for failed subversion authentication and improved error message for missing privileges
This commit is contained in:
@@ -37,6 +37,7 @@ package sonia.scm.util;
|
|||||||
|
|
||||||
import com.google.common.base.CharMatcher;
|
import com.google.common.base.CharMatcher;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -46,6 +47,7 @@ import sonia.scm.config.ScmConfiguration;
|
|||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
@@ -158,6 +160,9 @@ public final class HttpUtil
|
|||||||
public static final String STATUS_UNAUTHORIZED_MESSAGE =
|
public static final String STATUS_UNAUTHORIZED_MESSAGE =
|
||||||
"Authorization Required";
|
"Authorization Required";
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private static final int SKIP_SIZE = 4096;
|
||||||
|
|
||||||
/** the logger for HttpUtil */
|
/** the logger for HttpUtil */
|
||||||
private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);
|
private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);
|
||||||
|
|
||||||
@@ -167,7 +172,7 @@ public final class HttpUtil
|
|||||||
*/
|
*/
|
||||||
private static final Pattern PATTERN_URLNORMALIZE =
|
private static final Pattern PATTERN_URLNORMALIZE =
|
||||||
Pattern.compile("(?:(http://[^:]+):80(/.+)?|(https://[^:]+):443(/.+)?)");
|
Pattern.compile("(?:(http://[^:]+):80(/.+)?|(https://[^:]+):443(/.+)?)");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CharMatcher to select cr/lf and '%' characters
|
* CharMatcher to select cr/lf and '%' characters
|
||||||
* @since 1.28
|
* @since 1.28
|
||||||
@@ -197,10 +202,10 @@ public final class HttpUtil
|
|||||||
*/
|
*/
|
||||||
public static String append(String uri, String suffix)
|
public static String append(String uri, String suffix)
|
||||||
{
|
{
|
||||||
if ( uri.endsWith(SEPARATOR_PATH) && suffix.startsWith(SEPARATOR_PATH) )
|
if (uri.endsWith(SEPARATOR_PATH) && suffix.startsWith(SEPARATOR_PATH))
|
||||||
{
|
{
|
||||||
uri = uri.substring( 0, uri.length() - 1 );
|
uri = uri.substring(0, uri.length() - 1);
|
||||||
}
|
}
|
||||||
else if (!uri.endsWith(SEPARATOR_PATH) &&!suffix.startsWith(SEPARATOR_PATH))
|
else if (!uri.endsWith(SEPARATOR_PATH) &&!suffix.startsWith(SEPARATOR_PATH))
|
||||||
{
|
{
|
||||||
uri = uri.concat(SEPARATOR_PATH);
|
uri = uri.concat(SEPARATOR_PATH);
|
||||||
@@ -299,6 +304,38 @@ public final class HttpUtil
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips to complete body of a request.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request http request
|
||||||
|
*
|
||||||
|
* @since 1.37
|
||||||
|
*/
|
||||||
|
public static void drainBody(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
if (isChunked(request) || (request.getContentLength() > 0))
|
||||||
|
{
|
||||||
|
InputStream in = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
in = request.getInputStream();
|
||||||
|
|
||||||
|
while ((0 < in.skip(SKIP_SIZE)) || (0 <= in.read()))
|
||||||
|
{
|
||||||
|
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtil.close(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -443,10 +480,11 @@ public final class HttpUtil
|
|||||||
* @param realmDescription - realm description
|
* @param realmDescription - realm description
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*
|
*
|
||||||
* @since 1.36
|
* @since 1.36
|
||||||
*/
|
*/
|
||||||
public static void sendUnauthorized(HttpServletResponse response, String realmDescription)
|
public static void sendUnauthorized(HttpServletResponse response,
|
||||||
|
String realmDescription)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
sendUnauthorized(null, response, realmDescription);
|
sendUnauthorized(null, response, realmDescription);
|
||||||
@@ -465,8 +503,7 @@ public final class HttpUtil
|
|||||||
* @since 1.19
|
* @since 1.19
|
||||||
*/
|
*/
|
||||||
public static void sendUnauthorized(HttpServletRequest request,
|
public static void sendUnauthorized(HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response, String realmDescription)
|
||||||
String realmDescription)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if ((request == null) ||!isWUIRequest(request))
|
if ((request == null) ||!isWUIRequest(request))
|
||||||
@@ -671,6 +708,21 @@ public final class HttpUtil
|
|||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the body of the request is chunked.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request http request
|
||||||
|
*
|
||||||
|
* @return true if the request is chunked
|
||||||
|
*
|
||||||
|
* @since 1.37
|
||||||
|
*/
|
||||||
|
public static boolean isChunked(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
return "chunked".equals(request.getHeader("Transfer-Encoding"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the http request is send by the scm-manager web interface.
|
* Returns true if the http request is send by the scm-manager web interface.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.tmatesoft.svn.core.SVNErrorCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
public class ScmSvnErrorCode extends SVNErrorCode
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
public static final SVNErrorCode AUTHN_FAILED =
|
||||||
|
new ScmSvnErrorCode(AUTHN_CATEGORY, 4, "Authentication failed");
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
public static final SVNErrorCode AUTHZ_NOT_ENOUGH_PRIVILEGES =
|
||||||
|
new ScmSvnErrorCode(AUTHZ_CATEGORY, 4,
|
||||||
|
"You do not have enough access privileges for this operation.");
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private static final long serialVersionUID = -6864996390796610410L;
|
||||||
|
|
||||||
|
//~--- constructors ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs ...
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param category
|
||||||
|
* @param index
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
protected ScmSvnErrorCode(int category, int index, String description)
|
||||||
|
{
|
||||||
|
super(category, index, description);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,23 +37,37 @@ package sonia.scm.repository;
|
|||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.io.Closeables;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.tmatesoft.svn.core.SVNErrorCode;
|
||||||
import org.tmatesoft.svn.core.SVNLogEntry;
|
import org.tmatesoft.svn.core.SVNLogEntry;
|
||||||
import org.tmatesoft.svn.core.SVNLogEntryPath;
|
import org.tmatesoft.svn.core.SVNLogEntryPath;
|
||||||
|
import org.tmatesoft.svn.core.internal.io.dav.DAVElement;
|
||||||
|
import org.tmatesoft.svn.core.internal.server.dav.DAVXMLUtil;
|
||||||
|
import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
|
||||||
|
import org.tmatesoft.svn.core.internal.util.SVNXMLUtil;
|
||||||
import org.tmatesoft.svn.core.io.SVNRepository;
|
import org.tmatesoft.svn.core.io.SVNRepository;
|
||||||
import org.tmatesoft.svn.core.wc.SVNClientManager;
|
import org.tmatesoft.svn.core.wc.SVNClientManager;
|
||||||
import org.tmatesoft.svn.core.wc.admin.SVNChangeEntry;
|
import org.tmatesoft.svn.core.wc.admin.SVNChangeEntry;
|
||||||
|
|
||||||
|
import sonia.scm.util.HttpUtil;
|
||||||
import sonia.scm.util.Util;
|
import sonia.scm.util.Util;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -61,6 +75,12 @@ import java.util.Map;
|
|||||||
public final class SvnUtil
|
public final class SvnUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
public static final String XML_CONTENT_TYPE = "text/xml; charset=\"utf-8\"";
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private static final String HEADER_USERAGENT = "User-Agent";
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private static final String ID_TRANSACTION_PREFIX = "-1:";
|
private static final String ID_TRANSACTION_PREFIX = "-1:";
|
||||||
|
|
||||||
@@ -70,6 +90,9 @@ public final class SvnUtil
|
|||||||
*/
|
*/
|
||||||
private static final char TYPE_UPDATED = 'U';
|
private static final char TYPE_UPDATED = 'U';
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private static final String USERAGENT_SVN = "svn/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the logger for SvnUtil
|
* the logger for SvnUtil
|
||||||
*/
|
*/
|
||||||
@@ -232,6 +255,39 @@ public final class SvnUtil
|
|||||||
return changesets;
|
return changesets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
* @param errorCode
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String createErrorBody(SVNErrorCode errorCode)
|
||||||
|
{
|
||||||
|
StringBuffer xmlBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
SVNXMLUtil.addXMLHeader(xmlBuffer);
|
||||||
|
|
||||||
|
List<String> namespaces = Lists.newArrayList(DAVElement.DAV_NAMESPACE,
|
||||||
|
DAVElement.SVN_APACHE_PROPERTY_NAMESPACE);
|
||||||
|
|
||||||
|
SVNXMLUtil.openNamespaceDeclarationTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX,
|
||||||
|
DAVXMLUtil.SVN_DAV_ERROR_TAG, namespaces, SVNXMLUtil.PREFIX_MAP,
|
||||||
|
xmlBuffer);
|
||||||
|
|
||||||
|
SVNXMLUtil.openXMLTag(SVNXMLUtil.SVN_APACHE_PROPERTY_PREFIX,
|
||||||
|
"human-readable", SVNXMLUtil.XML_STYLE_NORMAL, "errcode",
|
||||||
|
String.valueOf(errorCode.getCode()), xmlBuffer);
|
||||||
|
xmlBuffer.append(
|
||||||
|
SVNEncodingUtil.xmlEncodeCDATA(errorCode.getDescription()));
|
||||||
|
SVNXMLUtil.closeXMLTag(SVNXMLUtil.SVN_APACHE_PROPERTY_PREFIX,
|
||||||
|
"human-readable", xmlBuffer);
|
||||||
|
SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX,
|
||||||
|
DAVXMLUtil.SVN_DAV_ERROR_TAG, xmlBuffer);
|
||||||
|
|
||||||
|
return xmlBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -266,6 +322,39 @@ public final class SvnUtil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param statusCode
|
||||||
|
* @param errorCode
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void sendError(HttpServletRequest request,
|
||||||
|
HttpServletResponse response, int statusCode, SVNErrorCode errorCode)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
HttpUtil.drainBody(request);
|
||||||
|
|
||||||
|
response.setStatus(statusCode);
|
||||||
|
response.setContentType(XML_CONTENT_TYPE);
|
||||||
|
|
||||||
|
PrintWriter writer = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
writer = response.getWriter();
|
||||||
|
writer.println(createErrorBody(errorCode));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Closeables.close(writer, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -311,6 +400,20 @@ public final class SvnUtil
|
|||||||
return id.substring(ID_TRANSACTION_PREFIX.length());
|
return id.substring(ID_TRANSACTION_PREFIX.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isSvnClient(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
return Strings.nullToEmpty(request.getHeader(HEADER_USERAGENT)).toLowerCase(
|
||||||
|
Locale.ENGLISH).startsWith(USERAGENT_SVN);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* 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.web;
|
||||||
|
|
||||||
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.tmatesoft.svn.core.SVNErrorCode;
|
||||||
|
|
||||||
|
import sonia.scm.config.ScmConfiguration;
|
||||||
|
import sonia.scm.repository.ScmSvnErrorCode;
|
||||||
|
import sonia.scm.repository.SvnUtil;
|
||||||
|
import sonia.scm.web.filter.AutoLoginModule;
|
||||||
|
import sonia.scm.web.filter.BasicAuthenticationFilter;
|
||||||
|
|
||||||
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import sonia.scm.util.HttpUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Sdorra
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class SvnBasicAuthenticationFilter extends BasicAuthenticationFilter
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs ...
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param configuration
|
||||||
|
* @param autoLoginModules
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
public SvnBasicAuthenticationFilter(ScmConfiguration configuration,
|
||||||
|
Set<AutoLoginModule> autoLoginModules)
|
||||||
|
{
|
||||||
|
super(configuration, autoLoginModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends unauthorized instead of forbidden for svn clients, because the
|
||||||
|
* svn client prompts again for authentication.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request http request
|
||||||
|
* @param response http response
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void sendFailedAuthenticationError(HttpServletRequest request,
|
||||||
|
HttpServletResponse response)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
if (SvnUtil.isSvnClient(request))
|
||||||
|
{
|
||||||
|
HttpUtil.sendUnauthorized(response, configuration.getRealmDescription());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
super.sendFailedAuthenticationError(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,15 +39,22 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.tmatesoft.svn.core.SVNErrorCode;
|
||||||
|
|
||||||
import sonia.scm.config.ScmConfiguration;
|
import sonia.scm.config.ScmConfiguration;
|
||||||
import sonia.scm.repository.RepositoryProvider;
|
import sonia.scm.repository.RepositoryProvider;
|
||||||
|
import sonia.scm.repository.ScmSvnErrorCode;
|
||||||
|
import sonia.scm.repository.SvnUtil;
|
||||||
import sonia.scm.web.filter.ProviderPermissionFilter;
|
import sonia.scm.web.filter.ProviderPermissionFilter;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -58,22 +65,16 @@ public class SvnPermissionFilter extends ProviderPermissionFilter
|
|||||||
{
|
{
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private static Set<String> WRITEMETHOD_SET = ImmutableSet.of("MKACTIVITY",
|
private static final Set<String> WRITEMETHOD_SET =
|
||||||
"PROPPATCH", "PUT",
|
ImmutableSet.of("MKACTIVITY", "PROPPATCH", "PUT", "CHECKOUT", "MKCOL",
|
||||||
"CHECKOUT", "MKCOL", "MOVE",
|
"MOVE", "COPY", "DELETE", "LOCK", "UNLOCK", "MERGE");
|
||||||
"COPY", "DELETE", "LOCK",
|
|
||||||
"UNLOCK", "MERGE");
|
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
//~--- constructors ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs ...
|
* Constructs ...
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param configuration
|
* @param configuration
|
||||||
* @param securityContextProvider
|
|
||||||
* @param repository
|
* @param repository
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
@@ -83,6 +84,33 @@ public class SvnPermissionFilter extends ProviderPermissionFilter
|
|||||||
super(configuration, repository);
|
super(configuration, repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void sendNotEnoughPrivilegesError(HttpServletRequest request,
|
||||||
|
HttpServletResponse response)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
if (SvnUtil.isSvnClient(request))
|
||||||
|
{
|
||||||
|
SvnUtil.sendError(request, response, HttpServletResponse.SC_FORBIDDEN,
|
||||||
|
ScmSvnErrorCode.AUTHZ_NOT_ENOUGH_PRIVILEGES);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
super.sendNotEnoughPrivilegesError(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class SvnServletModule extends ServletModule
|
|||||||
protected void configureServlets()
|
protected void configureServlets()
|
||||||
{
|
{
|
||||||
filter(PATTERN_SVN).through(SvnGZipFilter.class);
|
filter(PATTERN_SVN).through(SvnGZipFilter.class);
|
||||||
filter(PATTERN_SVN).through(BasicAuthenticationFilter.class);
|
filter(PATTERN_SVN).through(SvnBasicAuthenticationFilter.class);
|
||||||
filter(PATTERN_SVN).through(SvnPermissionFilter.class);
|
filter(PATTERN_SVN).through(SvnPermissionFilter.class);
|
||||||
|
|
||||||
Map<String, String> parameters = new HashMap<String, String>();
|
Map<String, String> parameters = new HashMap<String, String>();
|
||||||
|
|||||||
Reference in New Issue
Block a user