mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 16:35:45 +01:00
Add POC protocol servlet with delegate to git
This commit is contained in:
@@ -135,7 +135,7 @@ public class ScmContextListener extends GuiceResteasyBootstrapServletContextList
|
||||
moduleList.add(new EagerSingletonModule());
|
||||
moduleList.add(ShiroWebModule.guiceFilterModule());
|
||||
moduleList.add(new WebElementModule(pluginLoader));
|
||||
moduleList.add(new ScmServletModule(context, pluginLoader, overrides, pluginLoader.getExtensionProcessor()));
|
||||
moduleList.add(new ScmServletModule(context, pluginLoader, overrides));
|
||||
moduleList.add(
|
||||
new ScmSecurityModule(context, pluginLoader.getExtensionProcessor())
|
||||
);
|
||||
|
||||
@@ -56,17 +56,48 @@ import sonia.scm.group.xml.XmlGroupDAO;
|
||||
import sonia.scm.io.DefaultFileSystem;
|
||||
import sonia.scm.io.FileSystem;
|
||||
import sonia.scm.net.SSLContextProvider;
|
||||
import sonia.scm.net.ahc.*;
|
||||
import sonia.scm.plugin.*;
|
||||
import sonia.scm.repository.*;
|
||||
import sonia.scm.net.ahc.AdvancedHttpClient;
|
||||
import sonia.scm.net.ahc.ContentTransformer;
|
||||
import sonia.scm.net.ahc.DefaultAdvancedHttpClient;
|
||||
import sonia.scm.net.ahc.JsonContentTransformer;
|
||||
import sonia.scm.net.ahc.XmlContentTransformer;
|
||||
import sonia.scm.plugin.DefaultPluginLoader;
|
||||
import sonia.scm.plugin.DefaultPluginManager;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
import sonia.scm.plugin.PluginManager;
|
||||
import sonia.scm.repository.DefaultRepositoryManager;
|
||||
import sonia.scm.repository.DefaultRepositoryProvider;
|
||||
import sonia.scm.repository.HealthCheckContextListener;
|
||||
import sonia.scm.repository.NamespaceStrategy;
|
||||
import sonia.scm.repository.NamespaceStrategyProvider;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryDAO;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryManagerProvider;
|
||||
import sonia.scm.repository.RepositoryProvider;
|
||||
import sonia.scm.repository.api.HookContextFactory;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
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.*;
|
||||
import sonia.scm.store.*;
|
||||
import sonia.scm.security.AuthorizationChangedEventProducer;
|
||||
import sonia.scm.security.CipherHandler;
|
||||
import sonia.scm.security.CipherUtil;
|
||||
import sonia.scm.security.ConfigurableLoginAttemptHandler;
|
||||
import sonia.scm.security.DefaultKeyGenerator;
|
||||
import sonia.scm.security.DefaultSecuritySystem;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.security.LoginAttemptHandler;
|
||||
import sonia.scm.security.SecuritySystem;
|
||||
import sonia.scm.store.BlobStoreFactory;
|
||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
import sonia.scm.store.DataStoreFactory;
|
||||
import sonia.scm.store.FileBlobStoreFactory;
|
||||
import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.JAXBConfigurationStoreFactory;
|
||||
import sonia.scm.store.JAXBDataStoreFactory;
|
||||
import sonia.scm.template.MustacheTemplateEngine;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
@@ -81,6 +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.security.AdministrationContext;
|
||||
import sonia.scm.web.security.DefaultAdministrationContext;
|
||||
@@ -162,15 +194,12 @@ public class ScmServletModule extends ServletModule
|
||||
* @param servletContext
|
||||
* @param pluginLoader
|
||||
* @param overrides
|
||||
* @param extensionProcessor
|
||||
*/
|
||||
ScmServletModule(ServletContext servletContext,
|
||||
DefaultPluginLoader pluginLoader, ClassOverrides overrides, ExtensionProcessor extensionProcessor)
|
||||
ScmServletModule(ServletContext servletContext, DefaultPluginLoader pluginLoader, ClassOverrides overrides)
|
||||
{
|
||||
this.servletContext = servletContext;
|
||||
this.pluginLoader = pluginLoader;
|
||||
this.overrides = overrides;
|
||||
this.extensionProcessor = extensionProcessor;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -293,6 +322,8 @@ public class ScmServletModule extends ServletModule
|
||||
bind(TemplateEngineFactory.class);
|
||||
bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class);
|
||||
|
||||
filter("/repo/*").through(AuthenticationFilter.class);
|
||||
|
||||
// bind events
|
||||
// bind(LastModifiedUpdateListener.class);
|
||||
|
||||
@@ -389,11 +420,6 @@ public class ScmServletModule extends ServletModule
|
||||
|
||||
/**
|
||||
* Load ScmConfiguration with JAXB
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ScmConfiguration getScmConfiguration()
|
||||
{
|
||||
@@ -414,6 +440,4 @@ public class ScmServletModule extends ServletModule
|
||||
|
||||
/** Field description */
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final ExtensionProcessor extensionProcessor;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class WebResourceServlet extends HttpServlet {
|
||||
* TODO remove old protocol servlets and hook. Move /hook/hg to api?
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static final String PATTERN = "/(?!api/|git/|hg/|svn/|hook/).*";
|
||||
static final String PATTERN = "/(?!api/|git/|hg/|svn/|hook/|repo/).*";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WebResourceServlet.class);
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ package sonia.scm.repository;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.github.sdorra.ssp.PermissionActionCheck;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.google.inject.Inject;
|
||||
@@ -43,7 +42,6 @@ import org.apache.shiro.concurrent.SubjectAwareExecutorService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.AlreadyExistsException;
|
||||
import sonia.scm.ArgumentIsInvalidException;
|
||||
import sonia.scm.ConfigurationException;
|
||||
import sonia.scm.HandlerEventType;
|
||||
import sonia.scm.ManagerDaoAdapter;
|
||||
@@ -332,52 +330,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
uri = uri.substring(1);
|
||||
}
|
||||
|
||||
int typeSeparator = uri.indexOf(HttpUtil.SEPARATOR_PATH);
|
||||
Repository repository = null;
|
||||
|
||||
if (typeSeparator > 0) {
|
||||
String type = uri.substring(0, typeSeparator);
|
||||
String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH));
|
||||
String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1));
|
||||
|
||||
uri = uri.substring(typeSeparator + 1);
|
||||
repository = getFromTypeAndUri(type, uri);
|
||||
}
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
private Repository getFromTypeAndUri(String type, String uri) {
|
||||
if (Strings.isNullOrEmpty(type)) {
|
||||
throw new ArgumentIsInvalidException("argument type is required");
|
||||
}
|
||||
|
||||
if (Strings.isNullOrEmpty(uri)) {
|
||||
throw new ArgumentIsInvalidException("argument uri is required");
|
||||
}
|
||||
|
||||
// remove ;jsessionid, jetty bug?
|
||||
uri = HttpUtil.removeMatrixParameter(uri);
|
||||
|
||||
Repository repository = null;
|
||||
|
||||
if (handlerMap.containsKey(type)) {
|
||||
Collection<Repository> repositories = repositoryDAO.getAll();
|
||||
|
||||
PermissionActionCheck<Repository> check = RepositoryPermissions.read();
|
||||
|
||||
for (Repository r : repositories) {
|
||||
if (repositoryMatcher.matches(r, type, uri)) {
|
||||
check.check(r);
|
||||
repository = r.clone();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((repository == null) && logger.isDebugEnabled()) {
|
||||
logger.debug("could not find repository with type {} and uri {}", type,
|
||||
uri);
|
||||
}
|
||||
repository = get(new NamespaceAndName(namespace, name));
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
@@ -38,81 +38,31 @@ package sonia.scm.repository;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RequestScoped
|
||||
public class DefaultRepositoryProvider implements RepositoryProvider
|
||||
{
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@RequestScoped
|
||||
public class DefaultRepositoryProvider implements RepositoryProvider {
|
||||
|
||||
/** Field description */
|
||||
public static final String ATTRIBUTE_NAME = "scm.request.repository";
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param requestProvider
|
||||
* @param manager
|
||||
*/
|
||||
private final Provider<HttpServletRequest> requestProvider;
|
||||
@Inject
|
||||
public DefaultRepositoryProvider(
|
||||
Provider<HttpServletRequest> requestProvider,
|
||||
RepositoryManager manager)
|
||||
{
|
||||
public DefaultRepositoryProvider(Provider<HttpServletRequest> requestProvider) {
|
||||
this.requestProvider = requestProvider;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws ScmSecurityException
|
||||
*/
|
||||
@Override
|
||||
public Repository get() throws ScmSecurityException
|
||||
{
|
||||
Repository repository = null;
|
||||
public Repository get() throws ScmSecurityException {
|
||||
HttpServletRequest request = requestProvider.get();
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
repository = (Repository) request.getAttribute(ATTRIBUTE_NAME);
|
||||
|
||||
if (repository == null)
|
||||
{
|
||||
repository = manager.getFromRequest(request);
|
||||
|
||||
if (repository != null)
|
||||
{
|
||||
request.setAttribute(ATTRIBUTE_NAME, repository);
|
||||
}
|
||||
}
|
||||
if (request != null) {
|
||||
return (Repository) request.getAttribute(ATTRIBUTE_NAME);
|
||||
}
|
||||
|
||||
return repository;
|
||||
throw new IllegalStateException("request not found");
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final RepositoryManager manager;
|
||||
|
||||
/** Field description */
|
||||
private final Provider<HttpServletRequest> requestProvider;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package sonia.scm.web.protocol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import sonia.scm.PushStateDispatcher;
|
||||
import sonia.scm.filter.WebElement;
|
||||
import sonia.scm.repository.DefaultRepositoryProvider;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RepositoryProvider;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.repository.spi.HttpScmProtocol;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.web.UserAgent;
|
||||
import sonia.scm.web.UserAgentParser;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Singleton
|
||||
@WebElement(value = HttpProtocolServlet.PATTERN)
|
||||
@Slf4j
|
||||
public class HttpProtocolServlet extends HttpServlet {
|
||||
|
||||
public static final String PATTERN = "/repo/*";
|
||||
|
||||
private final RepositoryProvider repositoryProvider;
|
||||
private final RepositoryServiceFactory serviceFactory;
|
||||
|
||||
private final Provider<HttpServletRequest> requestProvider;
|
||||
|
||||
private final PushStateDispatcher dispatcher;
|
||||
private final UserAgentParser userAgentParser;
|
||||
|
||||
@Inject
|
||||
public HttpProtocolServlet(RepositoryProvider repositoryProvider, RepositoryServiceFactory serviceFactory, Provider<HttpServletRequest> requestProvider, PushStateDispatcher dispatcher, UserAgentParser userAgentParser) {
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
this.serviceFactory = serviceFactory;
|
||||
this.requestProvider = requestProvider;
|
||||
this.dispatcher = dispatcher;
|
||||
this.userAgentParser = userAgentParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
|
||||
|
||||
UserAgent userAgent = userAgentParser.parse(req);
|
||||
if (userAgent.isBrowser()) {
|
||||
log.trace("dispatch browser request for user agent {}", userAgent);
|
||||
dispatcher.dispatch(req, resp, req.getRequestURI());
|
||||
} else {
|
||||
|
||||
|
||||
String pathInfo = req.getPathInfo();
|
||||
NamespaceAndName namespaceAndName = fromUri(pathInfo);
|
||||
try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) {
|
||||
requestProvider.get().setAttribute(DefaultRepositoryProvider.ATTRIBUTE_NAME, repositoryService.getRepository());
|
||||
HttpScmProtocol protocol = repositoryService.getProtocol(HttpScmProtocol.class);
|
||||
protocol.serve(req, resp);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
resp.setStatus(404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private NamespaceAndName fromUri(String uri) {
|
||||
if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) {
|
||||
uri = uri.substring(1);
|
||||
}
|
||||
|
||||
String namespace = uri.substring(0, uri.indexOf(HttpUtil.SEPARATOR_PATH));
|
||||
String name = uri.substring(uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1, uri.indexOf(HttpUtil.SEPARATOR_PATH, uri.indexOf(HttpUtil.SEPARATOR_PATH) + 1));
|
||||
|
||||
return new NamespaceAndName(namespace, name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user