package com.atlassian.labs.speakeasy.git;
import com.atlassian.labs.speakeasy.external.SpeakeasyService;
import com.atlassian.plugin.PluginAccessor;
import com.atlassian.sal.api.user.UserManager;
import org.eclipse.jgit.http.server.GitServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static com.atlassian.labs.speakeasy.util.ExtensionValidate.isValidExtensionKey;
/**
*
*/
public class ExtensionGitServlet extends GitServlet
{
private final SpeakeasyService speakeasyService;
private final SpeakeasyRepositoryResolver speakeasyRepositoryResolver;
private final GitRepositoryManager gitRepositoryManager;
private final UserManager userManager;
private final PluginAccessor pluginAccessor;
private final Receive receive;
private static final Logger log = LoggerFactory.getLogger(ExtensionGitServlet.class);
public ExtensionGitServlet(UserManager userManager, SpeakeasyService speakeasyService, SpeakeasyRepositoryResolver speakeasyRepositoryResolver, GitRepositoryManager gitRepositoryManager, Receive receive, PluginAccessor pluginAccessor)
{
this.userManager = userManager;
this.speakeasyService = speakeasyService;
this.speakeasyRepositoryResolver = speakeasyRepositoryResolver;
this.gitRepositoryManager = gitRepositoryManager;
this.receive = receive;
this.pluginAccessor = pluginAccessor;
}
@Override
public void init(ServletConfig config) throws ServletException
{
addUploadPackFilter(new UploadPackFilter());
setReceivePackFactory(receive);
setRepositoryResolver(speakeasyRepositoryResolver);
super.init(config);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException
{
String user = userManager.getRemoteUsername(req);
if (user == null)
{
rsp.setHeader("WWW-Authenticate", "Basic realm=\"Speakeasy git server\"");
rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "");
}
else
{
createIfNecessary(req);
super.service(req, rsp);
}
}
/**
* Creates a git repository if none exist for Speakeasy authors. Unfortunately, in order to work, we have to do
* this on a GET request for the refs.
* @param req The request
*/
private void createIfNecessary(HttpServletRequest req)
{
String curInfo = req.getPathInfo();
final String suffix = "/info/refs";
if (curInfo != null && curInfo.length() > 0 && curInfo.endsWith(suffix))
{
String name = curInfo.substring(0, curInfo.length() - suffix.length());
if (name.length() > 0)
{
if (name.startsWith("/"))
{
name = name.substring(1);
}
String key = speakeasyRepositoryResolver.extractKeyFromUrl(name);
String user = userManager.getRemoteUsername(req);
if (pluginAccessor.getPlugin(key) == null && speakeasyService.canAuthorExtensions(user) && isValidExtensionKey(key))
{
log.info("Creating new extension '" + key + "' via git push");
// treat as a new plugin install
gitRepositoryManager.ensureRepository(key);
}
}
}
}
private class UploadPackFilter implements Filter
{
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
String user = userManager.getRemoteUsername((HttpServletRequest) request);
if (speakeasyService.canAuthorExtensions(user))
{
chain.doFilter(request, response);
}
}
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void destroy()
{
}
}
}