From cb285cbfddfc0b633d6b8cdb4dc0d2bd2b8b51ef Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Thu, 05 Jan 2012 17:34:05 -0500 Subject: [PATCH] Fixed bug in receive hook for repositories in subfolders --- src/com/gitblit/FederationServlet.java | 208 +++++++++++++++++++++++---------------------------- 1 files changed, 95 insertions(+), 113 deletions(-) diff --git a/src/com/gitblit/FederationServlet.java b/src/com/gitblit/FederationServlet.java index 784ec33..e772050 100644 --- a/src/com/gitblit/FederationServlet.java +++ b/src/com/gitblit/FederationServlet.java @@ -15,31 +15,28 @@ */ package com.gitblit; -import java.io.BufferedReader; +import java.io.File; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; -import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.gitblit.Constants.FederationRequest; -import com.gitblit.Constants.FederationToken; import com.gitblit.models.FederationModel; import com.gitblit.models.FederationProposal; -import com.gitblit.models.RepositoryModel; +import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; +import com.gitblit.utils.FederationUtils; +import com.gitblit.utils.FileUtils; import com.gitblit.utils.HttpUtils; import com.gitblit.utils.StringUtils; import com.gitblit.utils.TimeUtils; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; /** * Handles federation requests. @@ -47,69 +44,37 @@ * @author James Moger * */ -public class FederationServlet extends HttpServlet { +public class FederationServlet extends JsonServlet { private static final long serialVersionUID = 1L; - - private transient Logger logger = LoggerFactory.getLogger(FederationServlet.class); public FederationServlet() { super(); } /** - * Returns an url to this servlet for the specified parameters. - * - * @param sourceURL - * the url of the source gitblit instance - * @param token - * the federation token of the source gitblit instance - * @param req - * the pull type request - */ - public static String asFederationLink(String sourceURL, String token, FederationRequest req) { - return asFederationLink(sourceURL, null, token, req, null); - } - - /** - * - * @param remoteURL - * the url of the remote gitblit instance - * @param tokenType - * the type of federation token of a gitblit instance - * @param token - * the federation token of a gitblit instance - * @param req - * the pull type request - * @param myURL - * the url of this gitblit instance - * @return - */ - public static String asFederationLink(String remoteURL, FederationToken tokenType, - String token, FederationRequest req, String myURL) { - if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') { - remoteURL = remoteURL.substring(0, remoteURL.length() - 1); - } - if (req == null) { - req = FederationRequest.PULL_REPOSITORIES; - } - return remoteURL + Constants.FEDERATION_PATH + "?req=" + req.name().toLowerCase() - + (token == null ? "" : ("&token=" + token)) - + (tokenType == null ? "" : ("&tokenType=" + tokenType.name().toLowerCase())) - + (myURL == null ? "" : ("&url=" + StringUtils.encodeURL(myURL))); - } - - /** - * Returns the list of repositories for federation requests. + * Processes a federation request. * * @param request * @param response * @throws javax.servlet.ServletException * @throws java.io.IOException */ - private void processRequest(javax.servlet.http.HttpServletRequest request, + + @Override + protected void processRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { + FederationRequest reqType = FederationRequest.fromName(request.getParameter("req")); + logger.info(MessageFormat.format("Federation {0} request from {1}", reqType, + request.getRemoteAddr())); + + if (FederationRequest.POKE.equals(reqType)) { + // Gitblit always responds to POKE requests to verify a connection + logger.info("Received federation POKE from " + request.getRemoteAddr()); + return; + } + if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) { logger.warn(Keys.git.enableGitServlet + " must be set TRUE for federation requests."); response.sendError(HttpServletResponse.SC_FORBIDDEN); @@ -124,38 +89,32 @@ return; } - String token = request.getParameter("token"); - FederationRequest reqType = FederationRequest.fromName(request.getParameter("req")); - logger.info(MessageFormat.format("Federation {0} request from {1}", reqType, - request.getRemoteAddr())); - if (FederationRequest.PROPOSAL.equals(reqType)) { // Receive a gitblit federation proposal - BufferedReader reader = request.getReader(); - StringBuilder json = new StringBuilder(); - String line = null; - while ((line = reader.readLine()) != null) { - json.append(line); - } - reader.close(); - - // check to see if we have proposal data - if (json.length() == 0) { - logger.error(MessageFormat.format("Failed to receive proposal data from {0}", - request.getRemoteAddr())); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + FederationProposal proposal = deserialize(request, response, FederationProposal.class); + if (proposal == null) { return; } - - // deserialize the proposal - Gson gson = new Gson(); - FederationProposal proposal = gson.fromJson(json.toString(), FederationProposal.class); // reject proposal, if not receipt prohibited if (!GitBlit.getBoolean(Keys.federation.allowProposals, false)) { logger.error(MessageFormat.format("Rejected {0} federation proposal from {1}", proposal.tokenType.name(), proposal.url)); response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + + // poke the origin Gitblit instance that is proposing federation + boolean poked = false; + try { + poked = FederationUtils.poke(proposal.url); + } catch (Exception e) { + logger.error("Failed to poke origin", e); + } + if (!poked) { + logger.error(MessageFormat.format("Failed to send federation poke to {0}", + proposal.url)); + response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE); return; } @@ -173,25 +132,13 @@ String remoteId = StringUtils.decodeFromHtml(request.getParameter("url")); String identification = MessageFormat.format("{0} ({1})", remoteId, request.getRemoteAddr()); - BufferedReader reader = request.getReader(); - StringBuilder json = new StringBuilder(); - String line = null; - while ((line = reader.readLine()) != null) { - json.append(line); - } - reader.close(); - // check to see if we have repository data - if (json.length() == 0) { - logger.error(MessageFormat.format( - "Failed to receive pulled repositories list from {0}", identification)); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + // deserialize the status data + FederationModel results = deserialize(request, response, FederationModel.class); + if (results == null) { return; } - // deserialize the status data - Gson gson = new Gson(); - FederationModel results = gson.fromJson(json.toString(), FederationModel.class); // setup the last and netx pull dates results.lastPull = new Date(); int mins = TimeUtils.convertFrequencyToMinutes(results.frequency); @@ -207,6 +154,7 @@ } // Determine the federation tokens for this gitblit instance + String token = request.getParameter("token"); List<String> tokens = GitBlit.self().getFederationTokens(); if (!tokens.contains(token)) { logger.warn(MessageFormat.format( @@ -255,28 +203,62 @@ } } result = users; + } else if (FederationRequest.PULL_TEAMS.equals(reqType)) { + // pull teams + if (!GitBlit.self().validateFederationRequest(reqType, token)) { + // invalid token to pull teams + logger.warn(MessageFormat.format( + "Federation token from {0} not authorized to pull TEAMS", + request.getRemoteAddr())); + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + List<String> teamnames = GitBlit.self().getAllTeamnames(); + List<TeamModel> teams = new ArrayList<TeamModel>(); + for (String teamname : teamnames) { + TeamModel user = GitBlit.self().getTeamModel(teamname); + teams.add(user); + } + result = teams; + } else if (FederationRequest.PULL_SCRIPTS.equals(reqType)) { + // pull scripts + if (!GitBlit.self().validateFederationRequest(reqType, token)) { + // invalid token to pull script + logger.warn(MessageFormat.format( + "Federation token from {0} not authorized to pull SCRIPTS", + request.getRemoteAddr())); + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + Map<String, String> scripts = new HashMap<String, String>(); + + Set<String> names = new HashSet<String>(); + names.addAll(GitBlit.getStrings(Keys.groovy.preReceiveScripts)); + names.addAll(GitBlit.getStrings(Keys.groovy.postReceiveScripts)); + for (TeamModel team : GitBlit.self().getAllTeams()) { + names.addAll(team.preReceiveScripts); + names.addAll(team.postReceiveScripts); + } + File scriptsFolder = GitBlit.getFileOrFolder(Keys.groovy.scriptsFolder, "groovy"); + for (String name : names) { + File file = new File(scriptsFolder, name); + if (!file.exists() && !file.getName().endsWith(".groovy")) { + file = new File(scriptsFolder, name + ".groovy"); + } + if (file.exists()) { + // read the script + String content = FileUtils.readContent(file, "\n"); + scripts.put(name, content); + } else { + // missing script?! + logger.warn(MessageFormat.format("Failed to find push script \"{0}\"", name)); + } + } + result = scripts; } } - if (result != null) { - // Send JSON response - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String json = gson.toJson(result); - response.getWriter().append(json); - } - } - - @Override - protected void doPost(javax.servlet.http.HttpServletRequest request, - javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, - java.io.IOException { - processRequest(request, response); - } - - @Override - protected void doGet(javax.servlet.http.HttpServletRequest request, - javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, - java.io.IOException { - processRequest(request, response); + // send the result of the request + serialize(response, result); } } -- Gitblit v1.9.1