Avoid 500s when a topic includes changes that are not visible

/action and /submitted_together requests are throwing OrmException
when they are not able to examine non-visible changes in the topic:

 com.google.gwtorm.server.OrmException: Failed to get submit type for 12345: Patch set 12345,6 not found
        at com.google.gerrit.server.git.MergeSuperSet.logErrorAndThrow(MergeSuperSet.java:218)
        at com.google.gerrit.server.git.MergeSuperSet.completeChangeSetWithoutTopic(MergeSuperSet.java:122)
        at com.google.gerrit.server.git.MergeSuperSet.completeChangeSetIncludingTopics(MergeSuperSet.java:180)
        at com.google.gerrit.server.git.MergeSuperSet.completeChangeSet(MergeSuperSet.java:101)
        at com.google.gerrit.server.change.SubmittedTogether.getForOpenChange(SubmittedTogether.java:105)
        at com.google.gerrit.server.change.SubmittedTogether.apply(SubmittedTogether.java:78)
        at com.google.gerrit.server.change.SubmittedTogether.apply(SubmittedTogether.java:46)
        at com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:332)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

The result is a lightbox with a 500 when the user views a change in
the same topic as a draft change the user cannot see.

As a first step toward fixing that, use response code 403 instead.
This allows automated callers to get a better sense of what is going
on (it is a permissions error, not an internal server error) without
being confused by an unexpected response (e.g., an abbreviated list of
changes).

Change-Id: I560508c8d941fa6be140363f5bb103c3da4fac05
This commit is contained in:
Jonathan Nieder
2016-06-15 16:10:52 -07:00
parent 27d460cfa9
commit 669c6cf68b
8 changed files with 129 additions and 12 deletions

View File

@@ -16,21 +16,30 @@ package com.google.gerrit.acceptance.server.change;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
import static org.junit.Assert.fail;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.testutil.ConfigSuite;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Test;
public class SubmittedTogetherIT extends AbstractDaemonTest {
@ConfigSuite.Config
public static Config submitWholeTopicEnabled() {
return submitWholeTopicEnabledConfig();
}
@Test
public void returnsAncestors() throws Exception {
@@ -112,6 +121,34 @@ public class SubmittedTogetherIT extends AbstractDaemonTest {
}
}
@Test
public void hiddenDraftInTopic() throws Exception {
RevCommit initialHead = getRemoteHead();
RevCommit a = commitBuilder().add("a", "1").message("change 1").create();
pushHead(testRepo, "refs/for/master/" + name("topic"), false);
String id1 = getChangeId(a);
testRepo.reset(initialHead);
RevCommit b =
commitBuilder().add("b", "2").message("invisible change").create();
pushHead(testRepo, "refs/drafts/master/" + name("topic"), false);
setApiUser(user);
if (isSubmitWholeTopicEnabled()) {
try {
gApi.changes().id(id1).submittedTogether();
fail("Expected AuthException");
} catch (RestApiException e) {
// TODO(jrn): fix extension API not to wrap the RestApiException.
assertThat(e.getCause()).isInstanceOf(AuthException.class);
assertThat(e.getCause()).hasMessage(
"change would be submitted with a change that you cannot see");
}
} else {
assertSubmittedTogether(id1);
}
}
@Test
public void testTopicChaining() throws Exception {
RevCommit initialHead = getRemoteHead();