diff --git a/pom.xml b/pom.xml
index 9cf2da6d0b..a4d1254af4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -434,8 +434,8 @@
1.5.3
- 1.7.5
- 1.0.13
+ 1.7.6
+ 1.1.1
2.5
3.0
1.18
diff --git a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java
index 521f955e0f..338424d824 100644
--- a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java
+++ b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java
@@ -42,6 +42,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.event.ScmEventBus;
+import sonia.scm.util.HttpUtil;
import sonia.scm.xml.XmlSetStringAdapter;
//~--- JDK imports ------------------------------------------------------------
@@ -114,6 +115,7 @@ public class ScmConfiguration
*/
public void load(ScmConfiguration other)
{
+ this.realmDescription = other.realmDescription;
this.dateFormat = other.dateFormat;
this.pluginUrl = other.pluginUrl;
this.anonymousAccessEnabled = other.anonymousAccessEnabled;
@@ -129,6 +131,7 @@ public class ScmConfiguration
this.baseUrl = other.baseUrl;
this.disableGroupingGrid = other.disableGroupingGrid;
this.enableRepositoryArchive = other.enableRepositoryArchive;
+ this.skipFailedAuthenticators = other.skipFailedAuthenticators;
this.loginAttemptLimit = other.loginAttemptLimit;
this.loginAttemptLimitTimeout = other.loginAttemptLimitTimeout;
}
@@ -287,6 +290,18 @@ public class ScmConfiguration
return proxyUser;
}
+ /**
+ * Returns the realm description.
+ *
+ *
+ * @return realm description
+ */
+ public String getRealmDescription()
+ {
+ return realmDescription;
+ }
+
+
/**
* Returns true if the anonymous access to the SCM-Manager is enabled.
*
@@ -343,6 +358,19 @@ public class ScmConfiguration
return forceBaseUrl;
}
+ /**
+ * Returns true if failed authenticators are skipped.
+ *
+ *
+ * @return true if failed authenticators are skipped
+ *
+ * @since 1.36
+ */
+ public boolean isSkipFailedAuthenticators()
+ {
+ return skipFailedAuthenticators;
+ }
+
//~--- set methods ----------------------------------------------------------
/**
@@ -544,6 +572,30 @@ public class ScmConfiguration
this.proxyUser = proxyUser;
}
+ /**
+ * Sets the realm description.
+ *
+ *
+ * @param realmDescription
+ */
+ public void setRealmDescription(String realmDescription)
+ {
+ this.realmDescription = realmDescription;
+ }
+
+ /**
+ * If set to true the authentication chain is not stopped, if an
+ * authenticator finds the user but fails to authenticate the user.
+ *
+ * @param skipFailedAuthenticators true to skip failed authenticators
+ *
+ * @since 1.36
+ */
+ public void setSkipFailedAuthenticators(boolean skipFailedAuthenticators)
+ {
+ this.skipFailedAuthenticators = skipFailedAuthenticators;
+ }
+
//~--- fields ---------------------------------------------------------------
/** Field description */
@@ -572,21 +624,6 @@ public class ScmConfiguration
@XmlElement(name = "login-attempt-limit")
private int loginAttemptLimit = -1;
- /**
- * Login attempt timeout.
- *
- * @since 1.34
- */
- @XmlElement(name = "login-attempt-limit-timeout")
- private long loginAttemptLimitTimeout = TimeUnit.MINUTES.toSeconds(5l);
-
- /** Field description */
- private boolean enableProxy = false;
-
- /** Field description */
- @XmlElement(name = "plugin-url")
- private String pluginUrl = DEFAULT_PLUGINURL;
-
/** glob patterns for urls which are excluded from proxy */
@XmlElement(name = "proxy-excludes")
@XmlJavaTypeAdapter(XmlSetStringAdapter.class)
@@ -604,6 +641,36 @@ public class ScmConfiguration
/** Field description */
private String proxyUser;
+ /**
+ * Skip failed authenticators.
+ *
+ * @since 1.36
+ */
+ @XmlElement(name = "skip-failed-authenticators")
+ private boolean skipFailedAuthenticators = false;
+
+ /** Field description */
+ @XmlElement(name = "plugin-url")
+ private String pluginUrl = DEFAULT_PLUGINURL;
+
+ /**
+ * Login attempt timeout.
+ *
+ * @since 1.34
+ */
+ @XmlElement(name = "login-attempt-limit-timeout")
+ private long loginAttemptLimitTimeout = TimeUnit.MINUTES.toSeconds(5l);
+
+ /** Field description */
+ private boolean enableProxy = false;
+
+ /**
+ *
+ * Authentication realm for basic authentication.
+ *
+ */
+ private String realmDescription = HttpUtil.AUTHENTICATION_REALM;
+
/** Field description */
private boolean enableRepositoryArchive = false;
diff --git a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java
index f1ce453cc1..69f913d74d 100644
--- a/scm-core/src/main/java/sonia/scm/util/HttpUtil.java
+++ b/scm-core/src/main/java/sonia/scm/util/HttpUtil.java
@@ -416,7 +416,7 @@ public final class HttpUtil
throws IOException
{
- sendUnauthorized(null, response);
+ sendUnauthorized(null, response, AUTHENTICATION_REALM);
}
/**
@@ -427,17 +427,50 @@ public final class HttpUtil
* @param response http response
*
* @throws IOException
- *
- * @since 1.19
*/
public static void sendUnauthorized(HttpServletRequest request,
HttpServletResponse response)
throws IOException
+ {
+ sendUnauthorized(request, response, AUTHENTICATION_REALM);
+ }
+
+ /**
+ * Send an unauthorized header back to the client
+ *
+ *
+ * @param response - the http response
+ * @param realmDescription - realm description
+ *
+ * @throws IOException
+ */
+ public static void sendUnauthorized(HttpServletResponse response, String realmDescription)
+ throws IOException
+ {
+ sendUnauthorized(null, response, realmDescription);
+ }
+
+ /**
+ * Send an unauthorized header back to the client
+ *
+ *
+ * @param request http request
+ * @param response http response
+ * @param realmDescription realm description
+ *
+ * @throws IOException
+ *
+ * @since 1.19
+ */
+ public static void sendUnauthorized(HttpServletRequest request,
+ HttpServletResponse response,
+ String realmDescription)
+ throws IOException
{
if ((request == null) ||!isWUIRequest(request))
{
response.setHeader(HEADER_WWW_AUTHENTICATE,
- "Basic realm=\"".concat(AUTHENTICATION_REALM).concat("\""));
+ "Basic realm=\"".concat(realmDescription).concat("\""));
}
else if (logger.isTraceEnabled())
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java
index 21ad28b6ea..5992fd4cf7 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java
@@ -203,7 +203,7 @@ public class BasicAuthenticationFilter extends AutoLoginFilter
if (Strings.isNullOrEmpty(authentication))
{
- HttpUtil.sendUnauthorized(request, response);
+ HttpUtil.sendUnauthorized(request, response, configuration.getRealmDescription());
}
else
{
diff --git a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java
index 1b8b4dce11..9767f1d43e 100644
--- a/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java
+++ b/scm-core/src/main/java/sonia/scm/web/filter/PermissionFilter.java
@@ -245,7 +245,7 @@ public abstract class PermissionFilter extends HttpFilter
}
else
{
- HttpUtil.sendUnauthorized(response);
+ HttpUtil.sendUnauthorized(response, configuration.getRealmDescription());
}
}
diff --git a/scm-dao-xml/src/main/java/sonia/scm/xml/AbstractXmlDAO.java b/scm-dao-xml/src/main/java/sonia/scm/xml/AbstractXmlDAO.java
index 33765ce8a0..a0baa41034 100644
--- a/scm-dao-xml/src/main/java/sonia/scm/xml/AbstractXmlDAO.java
+++ b/scm-dao-xml/src/main/java/sonia/scm/xml/AbstractXmlDAO.java
@@ -34,6 +34,7 @@ package sonia.scm.xml;
//~--- non-JDK imports --------------------------------------------------------
+import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -229,7 +230,8 @@ public abstract class AbstractXmlDAO getAll()
{
- return db.values();
+ // avoid concurrent modification exceptions
+ return ImmutableList.copyOf(db.values());
}
/**
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/DBFormatHealthCheck.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/DBFormatHealthCheck.java
index c9958f24fb..1f90943e6f 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/DBFormatHealthCheck.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/DBFormatHealthCheck.java
@@ -77,7 +77,7 @@ public class DBFormatHealthCheck extends DirectoryHealthCheck
/** Field description */
private static final HealthCheckFailure INCOMPATIBLE_DB_FORMAT =
new HealthCheckFailure("AnOTx99ex1", "Incompatible DB Format",
- "https://bitbucket.org/sdorra/scm-manager/wiki/healtchecks/svn-incompatible-dbformat",
+ "https://bitbucket.org/sdorra/scm-manager/wiki/healthchecks/svn-incompatible-dbformat",
"The subversion db format is incompatible with the svn version used within scm-manager.");
/** Field description */
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/IllegalArgumentExceptionMapper.java b/scm-webapp/src/main/java/sonia/scm/api/rest/IllegalArgumentExceptionMapper.java
new file mode 100644
index 0000000000..32b6a02bc6
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/IllegalArgumentExceptionMapper.java
@@ -0,0 +1,64 @@
+/**
+ * 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;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ * @since 1.36
+ */
+@Provider
+public class IllegalArgumentExceptionMapper
+ implements ExceptionMapper
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param exception
+ *
+ * @return
+ */
+ @Override
+ public Response toResponse(IllegalArgumentException exception)
+ {
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java
index 507ab86b1f..29e47ef737 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java
@@ -35,6 +35,8 @@ package sonia.scm.api.rest.resources;
//~--- non-JDK imports --------------------------------------------------------
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.inject.Inject;
@@ -153,6 +155,7 @@ public class AuthenticationResource
*
*
* - 200 success
+ * - 400 bad request, required parameter is missing.
* - 401 unauthorized, the specified username or password is wrong
* - 500 internal server error
*
@@ -172,6 +175,11 @@ public class AuthenticationResource
@FormParam("password") String password, @FormParam("rememberMe")
@DefaultValue("false") boolean rememberMe)
{
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(username),
+ "username parameter is required");
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(password),
+ "password parameter is required");
+
Response response;
Subject subject = SecurityUtils.getSubject();
diff --git a/scm-webapp/src/main/java/sonia/scm/security/DefaultKeyGenerator.java b/scm-webapp/src/main/java/sonia/scm/security/DefaultKeyGenerator.java
index 2ed55e4487..149840b106 100644
--- a/scm-webapp/src/main/java/sonia/scm/security/DefaultKeyGenerator.java
+++ b/scm-webapp/src/main/java/sonia/scm/security/DefaultKeyGenerator.java
@@ -30,6 +30,7 @@
*/
+
package sonia.scm.security;
//~--- non-JDK imports --------------------------------------------------------
@@ -68,6 +69,17 @@ public class DefaultKeyGenerator implements KeyGenerator
//~--- methods --------------------------------------------------------------
+ /**
+ * Method description
+ *
+ *
+ * @param args
+ */
+ public static void main(String[] args)
+ {
+ System.out.println(new DefaultKeyGenerator().createKey());
+ }
+
/**
* Method description
*
@@ -107,8 +119,8 @@ public class DefaultKeyGenerator implements KeyGenerator
//~--- fields ---------------------------------------------------------------
/** Field description */
- private AtomicLong sessionKey = new AtomicLong();
+ private final AtomicLong sessionKey = new AtomicLong();
/** Field description */
- private Random random = new Random();
+ private final Random random = new Random();
}
diff --git a/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java b/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java
index 6fff389a3d..68a58cb124 100644
--- a/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java
+++ b/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java
@@ -361,7 +361,10 @@ public class ScmRealm extends AuthorizingRealm
// modify existing user, copy properties except password and admin
if (user.copyProperties(dbUser, false))
{
- userManager.modify(dbUser);
+ user.setLastModified(System.currentTimeMillis());
+ UserEventHack.fireEvent(userManager, HandlerEventType.BEFORE_MODIFY, user);
+ userDAO.modify(user);
+ UserEventHack.fireEvent(userManager, HandlerEventType.MODIFY, user);
}
}
diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java b/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java
index ff1310f22e..eeade3f1a2 100644
--- a/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java
+++ b/scm-webapp/src/main/java/sonia/scm/web/security/ChainAuthenticatonManager.java
@@ -47,6 +47,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
+import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.EncryptionHandler;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
@@ -85,19 +86,21 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
* Constructs ...
*
*
- *
+ * @param configuration
* @param userManager
* @param authenticationHandlerSet
* @param encryptionHandler
* @param cacheManager
*/
@Inject
- public ChainAuthenticatonManager(UserManager userManager,
+ public ChainAuthenticatonManager(ScmConfiguration configuration,
+ UserManager userManager,
Set authenticationHandlerSet,
EncryptionHandler encryptionHandler, CacheManager cacheManager)
{
AssertUtil.assertIsNotEmpty(authenticationHandlerSet);
AssertUtil.assertIsNotNull(cacheManager);
+ this.configuration = configuration;
this.authenticationHandlers = sort(userManager, authenticationHandlerSet);
this.encryptionHandler = encryptionHandler;
this.cache = cacheManager.getCache(CACHE_NAME);
@@ -190,6 +193,22 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
}
}
+ /**
+ * Method description
+ *
+ *
+ * @param result
+ *
+ * @return
+ */
+ boolean stopChain(AuthenticationResult result)
+ {
+ return (result != null) && (result.getState() != null)
+ && (result.getState().isSuccessfully()
+ || ((result.getState() == AuthenticationState.FAILED)
+ &&!configuration.isSkipFailedAuthenticators()));
+ }
+
/**
* Method description
*
@@ -230,9 +249,7 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
authenticator.getClass().getName(), result);
}
- if ((result != null) && (result.getState() != null)
- && (result.getState().isSuccessfully()
- || (result.getState() == AuthenticationState.FAILED)))
+ if (stopChain(result))
{
if (result.getState().isSuccessfully() && (result.getUser() != null))
{
@@ -372,7 +389,10 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
/** authentication cache */
private final Cache cache;
-
+
+ /** Field description */
+ private final ScmConfiguration configuration;
+
/** encryption handler */
private final EncryptionHandler encryptionHandler;
}
diff --git a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js
index 72b85e2e8a..29efa3fa00 100644
--- a/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js
+++ b/scm-webapp/src/main/webapp/resources/js/config/sonia.config.scmconfigpanel.js
@@ -34,6 +34,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
titleText: 'General Settings',
servnameText: 'Servername',
+ realmDescriptionText: 'Realm description',
dateFormatText: 'Date format',
enableForwardingText: 'Enable forwarding (mod_proxy)',
forwardPortText: 'Forward Port',
@@ -50,6 +51,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
errorSubmitMsgText: 'Could not submit config.',
// TODO i18n
+ skipFailedAuthenticatorsText: 'Skip failed authenticators',
loginAttemptLimitText: 'Login Attempt Limit',
loginAttemptLimitTimeoutText: 'Login Attempt Limit Timeout',
@@ -67,6 +69,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
// help
servernameHelpText: 'The name of this server. This name will be part of the repository url.',
+ realmDescriptionHelpText: 'Enter authentication realm description',
// TODO i18n
dateFormatHelpText: 'Moments date format. Please have a look at \n\
http://momentjs.com/docs/#/displaying/format/.
\n\
@@ -83,6 +86,8 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
adminUsersHelpText: 'Comma seperated list of users with admin permissions.',
// TODO i18n
+ skipFailedAuthenticatorsHelpText: 'Do not stop the authentication chain, \n\
+ if an authenticator finds the user but fails to authenticate the user.',
loginAttemptLimitHelpText: 'Maximum allowed login attempts. Use -1 to disable the login attempt limit.',
loginAttemptLimitTimeoutHelpText: 'Timeout in seconds for users which are temporary disabled,\
because of too many failed login attempts.',
@@ -129,6 +134,12 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
name: 'enableRepositoryArchive',
inputValue: 'true',
helpText: this.enableRepositoryArchiveHelpText
+ },{
+ xtype: 'textfield',
+ fieldLabel: this.realmDescriptionText,
+ name: 'realmDescription',
+ allowBlank: false,
+ helpText: this.realmDescriptionHelpText
},{
xtype: 'textfield',
fieldLabel: this.dateFormatText,
@@ -149,6 +160,12 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
name: 'anonymousAccessEnabled',
inputValue: 'true',
helpText: this.allowAnonymousAccessHelpText
+ },{
+ xtype: 'checkbox',
+ fieldLabel: this.skipFailedAuthenticatorsText,
+ name: 'skip-failed-authenticators',
+ inputValue: 'true',
+ helpText: this.skipFailedAuthenticatorsHelpText
},{
xtype: 'numberfield',
fieldLabel: this.loginAttemptLimitText,
diff --git a/scm-webapp/src/main/webapp/resources/js/i18n/de.js b/scm-webapp/src/main/webapp/resources/js/i18n/de.js
index 40b6b6dca6..6c8e00f8e4 100644
--- a/scm-webapp/src/main/webapp/resources/js/i18n/de.js
+++ b/scm-webapp/src/main/webapp/resources/js/i18n/de.js
@@ -40,7 +40,7 @@ if (Ext.form.VTypes){
passwordText: 'Die Passwörter stimmen nicht überein!',
nameTest: 'Der Name ist invalid.',
usernameText: 'Der Benutzername ist invalid.',
- repositoryNameText: 'Der Name des Repositorys ist ungültig.',
+ repositoryNameText: 'Der Name des Repositorys ist ungültig.'
});
}
@@ -349,6 +349,10 @@ if (Sonia.config.ScmConfigPanel){
adminGroupsHelpText: 'Komma getrennte Liste von Gruppen mit Administrationsrechten.',
adminUsersHelpText: 'Komma getrennte Liste von Benutzern mit Administrationsrechten.',
+ skipFailedAuthenticatorsText: 'Überspringe fehlgeschlagene Authentifizierer',
+ skipFailedAuthenticatorsHelpText: 'Setzt die Authentifizierungs-Kette fort,\n\
+ auch wenn ein ein Authentifizierer einen Benutzer gefunden hat,\n\
+ diesen aber nicht Authentifizieren kann.',
loginAttemptLimitText: 'Login Attempt Limit',
loginAttemptLimitTimeoutText: 'Login Attempt Limit Timeout',
loginAttemptLimitHelpText: 'Maximale Anzahl gescheiterte Loginversuche. Der Wert -1 deaktiviert die Begrenzung.',
diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js
index b6db7fb59f..99293a225d 100644
--- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js
+++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js
@@ -99,7 +99,8 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
},{
name: 'archived'
},{
- name: 'healthCheckFailures'
+ name: 'healthCheckFailures',
+ defaultValue: null
}]
}),
sortInfo: {
diff --git a/scm-webapp/src/test/java/sonia/scm/web/security/ChainAuthenticationManagerTest.java b/scm-webapp/src/test/java/sonia/scm/web/security/ChainAuthenticationManagerTest.java
index 1de9959a7b..1fa0ff384a 100644
--- a/scm-webapp/src/test/java/sonia/scm/web/security/ChainAuthenticationManagerTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/web/security/ChainAuthenticationManagerTest.java
@@ -42,6 +42,7 @@ import org.junit.Test;
import sonia.scm.AbstractTestBase;
import sonia.scm.SCMContextProvider;
import sonia.scm.cache.MapCacheManager;
+import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.MessageDigestEncryptionHandler;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
@@ -136,7 +137,7 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
SingleUserAuthenticaionHandler a2 =
new SingleUserAuthenticaionHandler("a2", trillian);
- manager = createManager("a2", a1, a2);
+ manager = createManager("a2", false, a1, a2);
AuthenticationResult result = manager.authenticate(request, response,
trillian.getName(), "trillian123");
@@ -146,6 +147,24 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
assertEquals("a2", result.getUser().getType());
}
+ /**
+ * Method description
+ *
+ */
+ @Test
+ public void testStopChain()
+ {
+ ChainAuthenticatonManager cam = createManager("", false);
+
+ assertTrue(cam.stopChain(new AuthenticationResult(perfect)));
+ assertTrue(cam.stopChain(AuthenticationResult.FAILED));
+ assertFalse(cam.stopChain(AuthenticationResult.NOT_FOUND));
+ cam = createManager("", true);
+ assertTrue(cam.stopChain(new AuthenticationResult(perfect)));
+ assertFalse(cam.stopChain(AuthenticationResult.FAILED));
+ assertFalse(cam.stopChain(AuthenticationResult.NOT_FOUND));
+ }
+
/**
* Method description
*
@@ -198,7 +217,7 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
trillian = UserTestData.createTrillian();
trillian.setPassword("trillian123");
- return createManager("",
+ return createManager("", false,
new SingleUserAuthenticaionHandler("perfectsType", perfect),
new SingleUserAuthenticaionHandler("trilliansType", trillian));
}
@@ -208,20 +227,33 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
*
*
* @param defaultType
+ * @param skipFailedAuthenticators
* @param handlers
*
* @return
*/
private ChainAuthenticatonManager createManager(String defaultType,
- AuthenticationHandler... handlers)
+ boolean skipFailedAuthenticators, AuthenticationHandler... handlers)
{
+ if ( handlers == null || handlers.length == 0 ){
+ //J-
+ handlers = new AuthenticationHandler[]{
+ new SingleUserAuthenticaionHandler("perfectsType", perfect),
+ new SingleUserAuthenticaionHandler("trilliansType", trillian)
+ };
+ //J+
+ }
+ ScmConfiguration configuration = new ScmConfiguration();
+
+ configuration.setSkipFailedAuthenticators(skipFailedAuthenticators);
+
Set handlerSet = ImmutableSet.copyOf(handlers);
UserManager userManager = mock(UserManager.class);
when(userManager.getDefaultType()).thenReturn(defaultType);
- manager = new ChainAuthenticatonManager(userManager, handlerSet,
- new MessageDigestEncryptionHandler(), new MapCacheManager());
+ manager = new ChainAuthenticatonManager(configuration, userManager,
+ handlerSet, new MessageDigestEncryptionHandler(), new MapCacheManager());
manager.init(contextProvider);
return manager;
@@ -326,10 +358,10 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
//~--- fields -------------------------------------------------------------
/** Field description */
- private String type;
+ private final String type;
/** Field description */
- private User user;
+ private final User user;
}