From 1d78b8b372f15d89f10fd32cb0227a6a7966de3c Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Thu, 17 Apr 2014 23:08:07 -0400 Subject: [PATCH] [findbugs] Clarify class used for resource loading --- src/main/java/com/gitblit/git/GitblitReceivePack.java | 180 +++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 141 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/gitblit/git/GitblitReceivePack.java b/src/main/java/com/gitblit/git/GitblitReceivePack.java index ba200b2..61f2d67 100644 --- a/src/main/java/com/gitblit/git/GitblitReceivePack.java +++ b/src/main/java/com/gitblit/git/GitblitReceivePack.java @@ -44,11 +44,14 @@ import com.gitblit.Constants; import com.gitblit.Constants.AccessRestrictionType; -import com.gitblit.GitBlit; +import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.client.Translation; +import com.gitblit.extensions.ReceiveHook; +import com.gitblit.manager.IGitblit; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; +import com.gitblit.tickets.BranchTicketService; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.ClientLogger; import com.gitblit.utils.CommitCache; @@ -84,18 +87,27 @@ protected String gitblitUrl; - protected String repositoryUrl; - protected GroovyScriptEngine gse; - public GitblitReceivePack(Repository db, RepositoryModel repository, UserModel user) { + protected final IStoredSettings settings; + + protected final IGitblit gitblit; + + public GitblitReceivePack( + IGitblit gitblit, + Repository db, + RepositoryModel repository, + UserModel user) { + super(db); + this.settings = gitblit.getSettings(); + this.gitblit = gitblit; this.repository = repository; - this.user = user == null ? UserModel.ANONYMOUS : user; - this.groovyDir = GitBlit.getGroovyScriptsFolder(); + this.user = user; + this.groovyDir = gitblit.getHooksFolder(); try { // set Grape root - File grapeRoot = GitBlit.getFileOrFolder(Keys.groovy.grapeFolder, "${baseFolder}/groovy/grape").getAbsoluteFile(); + File grapeRoot = gitblit.getGrapesFolder(); grapeRoot.mkdirs(); System.setProperty("grape.root", grapeRoot.getAbsolutePath()); this.gse = new GroovyScriptEngine(groovyDir.getAbsolutePath()); @@ -107,9 +119,46 @@ setAllowDeletes(user.canDeleteRef(repository)); setAllowNonFastForwards(user.canRewindRef(repository)); + int maxObjectSz = settings.getInteger(Keys.git.maxObjectSizeLimit, -1); + if (maxObjectSz >= 0) { + setMaxObjectSizeLimit(maxObjectSz); + } + int maxPackSz = settings.getInteger(Keys.git.maxPackSizeLimit, -1); + if (maxPackSz >= 0) { + setMaxPackSizeLimit(maxPackSz); + } + setCheckReceivedObjects(settings.getBoolean(Keys.git.checkReceivedObjects, true)); + setCheckReferencedObjectsAreReachable(settings.getBoolean(Keys.git.checkReferencedObjectsAreReachable, true)); + // setup pre and post receive hook setPreReceiveHook(this); setPostReceiveHook(this); + } + + /** + * Returns true if the user is permitted to apply the receive commands to + * the repository. + * + * @param commands + * @return true if the user may push these commands + */ + protected boolean canPush(Collection<ReceiveCommand> commands) { + // TODO Consider supporting branch permissions here (issue-36) + // Not sure if that should be Gerrit-style, refs/meta/config, or + // gitolite-style, permissions in users.conf + // + // How could commands be empty? + // + // Because a subclass, like PatchsetReceivePack, filters receive + // commands before this method is called. This makes it possible for + // this method to test an empty list. In this case, we assume that the + // subclass receive pack properly enforces push restrictions. for the + // ref. + // + // The empty test is not explicitly required, it's written here to + // clarify special-case behavior. + + return commands.isEmpty() ? true : user.canPush(repository); } /** @@ -119,6 +168,14 @@ */ @Override public void onPreReceive(ReceivePack rp, Collection<ReceiveCommand> commands) { + + if (commands.size() == 0) { + // no receive commands to process + // this can happen if receive pack subclasses intercept and filter + // the commands + LOGGER.debug("skipping pre-receive processing, no refs created, updated, or removed"); + return; + } if (repository.isMirror) { // repository is a mirror @@ -144,7 +201,7 @@ return; } - if (!user.canPush(repository)) { + if (!canPush(commands)) { // user does not have push permissions for (ReceiveCommand cmd : commands) { sendRejection(cmd, "User \"{0}\" does not have push permissions for \"{1}\"!", user.username, repository.name); @@ -155,8 +212,11 @@ if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH) && repository.verifyCommitter) { // enforce committer verification if (StringUtils.isEmpty(user.emailAddress)) { - // emit warning if user does not have an email address - LOGGER.warn(MessageFormat.format("Consider setting an email address for {0} ({1}) to improve committer verification.", user.getDisplayName(), user.username)); + // reject the push because the pushing account does not have an email address + for (ReceiveCommand cmd : commands) { + sendRejection(cmd, "Sorry, the account \"{0}\" does not have an email address set for committer verification!", user.username); + } + return; } // Optionally enforce that the committer of first parent chain @@ -189,16 +249,9 @@ PersonIdent committer = commit.getCommitterIdent(); if (!user.is(committer.getName(), committer.getEmailAddress())) { - String reason; - if (StringUtils.isEmpty(user.emailAddress)) { - // account does not have an email address - reason = MessageFormat.format("{0} by {1} <{2}> was not committed by {3} ({4})", - commit.getId().name(), committer.getName(), StringUtils.isEmpty(committer.getEmailAddress()) ? "?":committer.getEmailAddress(), user.getDisplayName(), user.username); - } else { - // account has an email address - reason = MessageFormat.format("{0} by {1} <{2}> was not committed by {3} ({4}) <{5}>", - commit.getId().name(), committer.getName(), StringUtils.isEmpty(committer.getEmailAddress()) ? "?":committer.getEmailAddress(), user.getDisplayName(), user.username, user.emailAddress); - } + // verification failed + String reason = MessageFormat.format("{0} by {1} <{2}> was not committed by {3} ({4}) <{5}>", + commit.getId().name(), committer.getName(), StringUtils.isEmpty(committer.getEmailAddress()) ? "?":committer.getEmailAddress(), user.getDisplayName(), user.username, user.emailAddress); LOGGER.warn(reason); cmd.setResult(Result.REJECTED_OTHER_REASON, reason); allRejected &= true; @@ -218,23 +271,42 @@ } } - // reset branch commit cache on REWIND and DELETE for (ReceiveCommand cmd : commands) { String ref = cmd.getRefName(); if (ref.startsWith(Constants.R_HEADS)) { switch (cmd.getType()) { case UPDATE_NONFASTFORWARD: case DELETE: + // reset branch commit cache on REWIND and DELETE CommitCache.instance().clear(repository.name, ref); break; default: break; } + } else if (ref.equals(BranchTicketService.BRANCH)) { + // ensure pushing user is an administrator OR an owner + // i.e. prevent ticket tampering + boolean permitted = user.canAdmin() || repository.isOwner(user.username); + if (!permitted) { + sendRejection(cmd, "{0} is not permitted to push to {1}", user.username, ref); + } + } else if (ref.startsWith(Constants.R_FOR)) { + // prevent accidental push to refs/for + sendRejection(cmd, "{0} is not configured to receive patchsets", repository.name); + } + } + + // call pre-receive plugins + for (ReceiveHook hook : gitblit.getExtensions(ReceiveHook.class)) { + try { + hook.onPreReceive(this, commands); + } catch (Exception e) { + LOGGER.error("Failed to execute extension", e); } } Set<String> scripts = new LinkedHashSet<String>(); - scripts.addAll(GitBlit.self().getPreReceiveScriptsInherited(repository)); + scripts.addAll(gitblit.getPreReceiveScriptsInherited(repository)); if (!ArrayUtils.isEmpty(repository.preReceiveScripts)) { scripts.addAll(repository.preReceiveScripts); } @@ -255,7 +327,7 @@ @Override public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) { if (commands.size() == 0) { - LOGGER.debug("skipping post-receive hooks, no refs created, updated, or removed"); + LOGGER.debug("skipping post-receive processing, no refs created, updated, or removed"); return; } @@ -303,7 +375,7 @@ String msg = MessageFormat.format(template, branch); String prefix; if (StringUtils.isEmpty(repository.incrementalPushTagPrefix)) { - prefix = GitBlit.getString(Keys.git.defaultIncrementalPushTagPrefix, "r"); + prefix = settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r"); } else { prefix = repository.incrementalPushTagPrefix; } @@ -327,9 +399,27 @@ LOGGER.error(MessageFormat.format("Failed to update {0} pushlog", repository.name), e); } + // check for updates pushed to the BranchTicketService branch + // if the BranchTicketService is active it will reindex, as appropriate + for (ReceiveCommand cmd : commands) { + if (Result.OK.equals(cmd.getResult()) + && BranchTicketService.BRANCH.equals(cmd.getRefName())) { + rp.getRepository().fireEvent(new ReceiveCommandEvent(repository, cmd)); + } + } + + // call post-receive plugins + for (ReceiveHook hook : gitblit.getExtensions(ReceiveHook.class)) { + try { + hook.onPostReceive(this, commands); + } catch (Exception e) { + LOGGER.error("Failed to execute extension", e); + } + } + // run Groovy hook scripts Set<String> scripts = new LinkedHashSet<String>(); - scripts.addAll(GitBlit.self().getPostReceiveScriptsInherited(repository)); + scripts.addAll(gitblit.getPostReceiveScriptsInherited(repository)); if (!ArrayUtils.isEmpty(repository.postReceiveScripts)) { scripts.addAll(repository.postReceiveScripts); } @@ -382,11 +472,7 @@ this.gitblitUrl = url; } - protected void setRepositoryUrl(String url) { - this.repositoryUrl = url; - } - - protected void sendRejection(final ReceiveCommand cmd, final String why, Object... objects) { + public void sendRejection(final ReceiveCommand cmd, final String why, Object... objects) { String text; if (ArrayUtils.isEmpty(objects)) { text = why; @@ -397,15 +483,15 @@ LOGGER.error(text + " (" + user.username + ")"); } - protected void sendHeader(String msg, Object... objects) { - sendMessage("--->", msg, objects); + public void sendHeader(String msg, Object... objects) { + sendInfo("--> ", msg, objects); } - protected void sendMessage(String msg, Object... objects) { - sendMessage(" ", msg, objects); + public void sendInfo(String msg, Object... objects) { + sendInfo(" ", msg, objects); } - protected void sendMessage(String prefix, String msg, Object... objects) { + private void sendInfo(String prefix, String msg, Object... objects) { String text; if (ArrayUtils.isEmpty(objects)) { text = msg; @@ -414,10 +500,12 @@ text = MessageFormat.format(msg, objects); super.sendMessage(prefix + text); } - LOGGER.info(text + " (" + user.username + ")"); + if (!StringUtils.isEmpty(msg)) { + LOGGER.info(text + " (" + user.username + ")"); + } } - protected void sendError(String msg, Object... objects) { + public void sendError(String msg, Object... objects) { String text; if (ArrayUtils.isEmpty(objects)) { text = msg; @@ -426,7 +514,9 @@ text = MessageFormat.format(msg, objects); super.sendError(text); } - LOGGER.error(text + " (" + user.username + ")"); + if (!StringUtils.isEmpty(msg)) { + LOGGER.error(text + " (" + user.username + ")"); + } } /** @@ -444,7 +534,7 @@ } Binding binding = new Binding(); - binding.setVariable("gitblit", GitBlit.self()); + binding.setVariable("gitblit", gitblit); binding.setVariable("repository", repository); binding.setVariable("receivePack", this); binding.setVariable("user", user); @@ -480,4 +570,16 @@ } } } + + public IGitblit getGitblit() { + return gitblit; + } + + public RepositoryModel getRepositoryModel() { + return repository; + } + + public UserModel getUserModel() { + return user; + } } -- Gitblit v1.9.1