Merge with 2.0.0-m3

This commit is contained in:
René Pfeuffer
2018-12-21 14:08:46 +01:00
118 changed files with 4004 additions and 12137 deletions

View File

@@ -79,14 +79,14 @@ import sonia.scm.repository.spi.HookEventFacade;
import sonia.scm.repository.xml.XmlRepositoryDAO;
import sonia.scm.schedule.QuartzScheduler;
import sonia.scm.schedule.Scheduler;
import sonia.scm.security.AccessTokenCookieIssuer;
import sonia.scm.security.AuthorizationChangedEventProducer;
import sonia.scm.security.CipherHandler;
import sonia.scm.security.CipherUtil;
import sonia.scm.security.ConfigurableLoginAttemptHandler;
import sonia.scm.security.DefaultJwtAccessTokenRefreshStrategy;
import sonia.scm.security.DefaultAccessTokenCookieIssuer;
import sonia.scm.security.DefaultKeyGenerator;
import sonia.scm.security.DefaultSecuritySystem;
import sonia.scm.security.JwtAccessTokenRefreshStrategy;
import sonia.scm.security.KeyGenerator;
import sonia.scm.security.LoginAttemptHandler;
import sonia.scm.security.SecuritySystem;
@@ -112,9 +112,7 @@ import sonia.scm.util.ScmConfigurationUtil;
import sonia.scm.web.UserAgentParser;
import sonia.scm.web.cgi.CGIExecutorFactory;
import sonia.scm.web.cgi.DefaultCGIExecutorFactory;
import sonia.scm.web.filter.AuthenticationFilter;
import sonia.scm.web.filter.LoggingFilter;
import sonia.scm.web.protocol.HttpProtocolServlet;
import sonia.scm.web.security.AdministrationContext;
import sonia.scm.web.security.DefaultAdministrationContext;
@@ -315,11 +313,10 @@ public class ScmServletModule extends ServletModule
bind(TemplateEngineFactory.class);
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class);
filter(HttpProtocolServlet.PATTERN).through(AuthenticationFilter.class);
// bind events
// bind(LastModifiedUpdateListener.class);
bind(AccessTokenCookieIssuer.class).to(DefaultAccessTokenCookieIssuer.class);
bind(PushStateDispatcher.class).toProvider(PushStateDispatcherProvider.class);
}

View File

@@ -20,7 +20,7 @@ public class FallbackExceptionMapper implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
logger.debug("map exception to status code 500", exception);
logger.warn("mapping unexpected {} to status code 500", exception.getClass().getName(), exception);
ErrorDto errorDto = new ErrorDto();
errorDto.setMessage("internal server error");
errorDto.setContext(Collections.emptyList());

View File

@@ -0,0 +1,35 @@
package sonia.scm.api;
import com.fasterxml.jackson.core.JsonParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import sonia.scm.api.v2.resources.ErrorDto;
import sonia.scm.web.VndMediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import java.util.Collections;
@Provider
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
private static final Logger logger = LoggerFactory.getLogger(JsonParseExceptionMapper.class);
private static final String ERROR_CODE = "2VRCrvpL71";
@Override
public Response toResponse(JsonParseException exception) {
logger.trace("got illegal json: {}", exception.getMessage());
ErrorDto errorDto = new ErrorDto();
errorDto.setMessage("illegal json content: " + exception.getMessage());
errorDto.setContext(Collections.emptyList());
errorDto.setErrorCode(ERROR_CODE);
errorDto.setTransactionId(MDC.get("transaction_id"));
return Response.status(Response.Status.BAD_REQUEST)
.entity(errorDto)
.type(VndMediaType.ERROR_TYPE)
.build();
}
}

View File

@@ -36,6 +36,7 @@ package sonia.scm.api.rest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
@@ -92,6 +93,7 @@ public class StatusExceptionMapper<E extends Throwable>
return Response.status(status)
.entity(exception.getMessage())
.type(MediaType.TEXT_PLAIN_TYPE)
.build();
}
}

View File

@@ -51,12 +51,12 @@ import java.util.concurrent.TimeUnit;
* @author Sebastian Sdorra
* @since 2.0.0
*/
public final class AccessTokenCookieIssuer {
public final class DefaultAccessTokenCookieIssuer implements AccessTokenCookieIssuer {
/**
* the logger for AccessTokenCookieIssuer
* the logger for DefaultAccessTokenCookieIssuer
*/
private static final Logger LOG = LoggerFactory.getLogger(AccessTokenCookieIssuer.class);
private static final Logger LOG = LoggerFactory.getLogger(DefaultAccessTokenCookieIssuer.class);
private final ScmConfiguration configuration;
@@ -66,7 +66,7 @@ public final class AccessTokenCookieIssuer {
* @param configuration scm main configuration
*/
@Inject
public AccessTokenCookieIssuer(ScmConfiguration configuration) {
public DefaultAccessTokenCookieIssuer(ScmConfiguration configuration) {
this.configuration = configuration;
}

View File

@@ -87,6 +87,7 @@ public final class JwtAccessToken implements AccessToken {
return ofNullable(claims.get(REFRESHABLE_UNTIL_CLAIM_KEY, Date.class));
}
@Override
public Optional<String> getParentKey() {
return ofNullable(claims.get(PARENT_TOKEN_ID_CLAIM_KEY).toString());
}

View File

@@ -0,0 +1,50 @@
package sonia.scm.web.filter;
import sonia.scm.Priority;
import sonia.scm.PushStateDispatcher;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.filter.Filters;
import sonia.scm.filter.WebElement;
import sonia.scm.util.HttpUtil;
import sonia.scm.web.UserAgent;
import sonia.scm.web.UserAgentParser;
import sonia.scm.web.WebTokenGenerator;
import sonia.scm.web.protocol.HttpProtocolServlet;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
import static sonia.scm.util.HttpUtil.AUTHENTICATION_REALM;
import static sonia.scm.util.HttpUtil.HEADER_WWW_AUTHENTICATE;
@Priority(Filters.PRIORITY_AUTHENTICATION)
@WebElement(value = HttpProtocolServlet.PATTERN)
public class HttpProtocolServletAuthenticationFilter extends AuthenticationFilter {
private final PushStateDispatcher dispatcher;
private final UserAgentParser userAgentParser;
@Inject
public HttpProtocolServletAuthenticationFilter(
ScmConfiguration configuration,
Set<WebTokenGenerator> tokenGenerators,
PushStateDispatcher dispatcher,
UserAgentParser userAgentParser) {
super(configuration, tokenGenerators);
this.dispatcher = dispatcher;
this.userAgentParser = userAgentParser;
}
@Override
protected void sendUnauthorizedError(HttpServletRequest request, HttpServletResponse response) throws IOException {
UserAgent userAgent = userAgentParser.parse(request);
if (userAgent.isBrowser()) {
dispatcher.dispatch(request, response, request.getRequestURI());
} else {
HttpUtil.sendUnauthorized(request, response);
}
}
}