Merge branch 'stable-3.5' into stable-3.6 * stable-3.5: Allow update head with Fetch replication global capability Revert "Reuse Gerrit code for head update" Fix pull-replication update head with Gerrit replica Ignore all broken tests on Gerrit replica Add indirect commons-lang3 dependency Do not provide response body when apply-object is successful Change-Id: Idb606e474edff9d398290c7847a3834737689b09
diff --git a/BUILD b/BUILD index 7646282..0983983 100644 --- a/BUILD +++ b/BUILD
@@ -17,6 +17,7 @@ deps = [ "//lib/commons:io", "//plugins/replication", + "@commons-lang3//jar", "@events-broker//jar:neverlink", ], )
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectAction.java index b3379f2..72f0266 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectAction.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectAction.java
@@ -102,7 +102,7 @@ input.getRevisionData(), input.getLabel(), input.getEventCreatedOn()); - return Response.created(input); + return Response.created(); } catch (MissingParentObjectException e) { repLog.error( "Apply object API *FAILED* from {} for {}:{} - {}",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectsAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectsAction.java index dd155d4..817ea00 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectsAction.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectsAction.java
@@ -102,7 +102,7 @@ input.getRevisionsData(), input.getLabel(), input.getEventCreatedOn()); - return Response.created(input); + return Response.created(); } catch (MissingParentObjectException e) { repLog.error( "Apply object API *FAILED* from {} for {}:{} - {}",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchPreconditions.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchPreconditions.java index 161bcf4..77d0e0b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchPreconditions.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchPreconditions.java
@@ -16,13 +16,17 @@ import static com.googlesource.gerrit.plugins.replication.pull.api.FetchApiCapability.CALL_FETCH_ACTION; +import com.google.gerrit.entities.Project; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.api.access.PluginPermission; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.permissions.GlobalPermission; import com.google.gerrit.server.permissions.PermissionBackend; +import com.google.gerrit.server.permissions.PermissionBackendException; +import com.google.gerrit.server.permissions.RefPermission; import com.google.inject.Inject; import com.google.inject.Provider; +import com.googlesource.gerrit.plugins.replication.pull.api.exception.UnauthorizedAuthException; public class FetchPreconditions { private final String pluginName; @@ -39,11 +43,31 @@ this.permissionBackend = permissionBackend; } - public Boolean canCallFetchApi() { - CurrentUser currentUser = userProvider.get(); - PermissionBackend.WithUser userPermission = permissionBackend.user(currentUser); + public Boolean canCallFetchApi() throws UnauthorizedAuthException { + CurrentUser currentUser = currentUser(); + return canCallFetchApi(currentUser, permissionBackend.user(currentUser)); + } + + private Boolean canCallFetchApi( + CurrentUser currentUser, PermissionBackend.WithUser userPermission) { return currentUser.isInternalUser() || userPermission.testOrFalse(GlobalPermission.ADMINISTRATE_SERVER) || userPermission.testOrFalse(new PluginPermission(pluginName, CALL_FETCH_ACTION)); } + + public Boolean canCallUpdateHeadApi(Project.NameKey projectNameKey, String ref) + throws PermissionBackendException, UnauthorizedAuthException { + CurrentUser currentUser = currentUser(); + PermissionBackend.WithUser userAcls = permissionBackend.user(currentUser); + return canCallFetchApi(currentUser, userAcls) + || userAcls.project(projectNameKey).ref(ref).test(RefPermission.SET_HEAD); + } + + private CurrentUser currentUser() throws UnauthorizedAuthException { + CurrentUser currentUser = userProvider.get(); + if (!currentUser.isIdentifiedUser() && !currentUser.isInternalUser()) { + throw new UnauthorizedAuthException(); + } + return currentUser; + } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java index 4d932d4..e54d408 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilter.java
@@ -23,6 +23,7 @@ import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_OK; +import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; import com.google.common.flogger.FluentLogger; import com.google.gerrit.extensions.annotations.PluginName; @@ -52,6 +53,7 @@ import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionInput; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionsInput; import com.googlesource.gerrit.plugins.replication.pull.api.exception.InitProjectException; +import com.googlesource.gerrit.plugins.replication.pull.api.exception.UnauthorizedAuthException; import java.io.BufferedReader; import java.io.EOFException; import java.io.IOException; @@ -136,6 +138,9 @@ chain.doFilter(request, response); } + } catch (UnauthorizedAuthException e) { + RestApiServlet.replyError( + httpRequest, httpResponse, SC_UNAUTHORIZED, e.getMessage(), e.caching(), e); } catch (AuthException e) { RestApiServlet.replyError( httpRequest, httpResponse, SC_FORBIDDEN, e.getMessage(), e.caching(), e); @@ -182,23 +187,23 @@ } @SuppressWarnings("unchecked") - private Response<Map<String, Object>> doApplyObject(HttpServletRequest httpRequest) + private Response<String> doApplyObject(HttpServletRequest httpRequest) throws RestApiException, IOException, PermissionBackendException { RevisionInput input = readJson(httpRequest, TypeLiteral.get(RevisionInput.class)); IdString id = getProjectName(httpRequest).get(); ProjectResource projectResource = projectsCollection.parse(TopLevelResource.INSTANCE, id); - return (Response<Map<String, Object>>) applyObjectAction.apply(projectResource, input); + return (Response<String>) applyObjectAction.apply(projectResource, input); } @SuppressWarnings("unchecked") - private Response<Map<String, Object>> doApplyObjects(HttpServletRequest httpRequest) + private Response<String> doApplyObjects(HttpServletRequest httpRequest) throws RestApiException, IOException, PermissionBackendException { RevisionsInput input = readJson(httpRequest, TypeLiteral.get(RevisionsInput.class)); IdString id = getProjectName(httpRequest).get(); ProjectResource projectResource = projectsCollection.parse(TopLevelResource.INSTANCE, id); - return (Response<Map<String, Object>>) applyObjectsAction.apply(projectResource, input); + return (Response<String>) applyObjectsAction.apply(projectResource, input); } @SuppressWarnings("unchecked") @@ -321,7 +326,9 @@ } private boolean isUpdateHEADAction(HttpServletRequest httpRequest) { - return httpRequest.getRequestURI().matches(".*/projects/[^/]+/HEAD") + return httpRequest + .getRequestURI() + .matches(String.format(".*/projects/[^/]+/%s~HEAD", pluginName)) && "PUT".equals(httpRequest.getMethod()); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java index ae9c072..3f6673b 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadAction.java
@@ -14,28 +14,62 @@ package com.googlesource.gerrit.plugins.replication.pull.api; +import com.google.common.base.Strings; +import com.google.gerrit.entities.RefNames; import com.google.gerrit.extensions.api.projects.HeadInput; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.ResourceConflictException; +import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.extensions.restapi.RestModifyView; +import com.google.gerrit.extensions.restapi.UnprocessableEntityException; import com.google.gerrit.server.project.ProjectResource; -import com.google.gerrit.server.restapi.project.SetHead; import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.googlesource.gerrit.plugins.replication.LocalFS; +import com.googlesource.gerrit.plugins.replication.pull.GerritConfigOps; +import java.util.Optional; +import org.eclipse.jgit.transport.URIish; +@Singleton public class UpdateHeadAction implements RestModifyView<ProjectResource, HeadInput> { - - private final SetHead setHead; + private final GerritConfigOps gerritConfigOps; + private final FetchPreconditions preconditions; @Inject - public UpdateHeadAction(SetHead setHead) { - this.setHead = setHead; + UpdateHeadAction(GerritConfigOps gerritConfigOps, FetchPreconditions preconditions) { + this.gerritConfigOps = gerritConfigOps; + this.preconditions = preconditions; } @Override - public Response<?> apply(ProjectResource resource, HeadInput input) + public Response<?> apply(ProjectResource projectResource, HeadInput input) throws AuthException, BadRequestException, ResourceConflictException, Exception { - return setHead.apply(resource, input); + if (input == null || Strings.isNullOrEmpty(input.ref)) { + throw new BadRequestException("ref required"); + } + String ref = RefNames.fullName(input.ref); + + if (!preconditions.canCallUpdateHeadApi(projectResource.getNameKey(), ref)) { + throw new AuthException("Update head not permitted"); + } + + // TODO: the .git suffix should not be added here, but rather it should be + // dealt with by the caller, honouring the naming style from the + // replication.config (Issue 15221) + Optional<URIish> maybeRepo = + gerritConfigOps.getGitRepositoryURI(String.format("%s.git", projectResource.getName())); + + if (maybeRepo.isPresent()) { + if (new LocalFS(maybeRepo.get()).updateHead(projectResource.getNameKey(), ref)) { + return Response.ok(ref); + } + throw new UnprocessableEntityException( + String.format( + "Could not update HEAD of repo %s to ref %s", projectResource.getName(), ref)); + } + throw new ResourceNotFoundException( + String.format("Could not compute URL for repo: %s", projectResource.getName())); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/exception/UnauthorizedAuthException.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/exception/UnauthorizedAuthException.java new file mode 100644 index 0000000..9afac22 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/exception/UnauthorizedAuthException.java
@@ -0,0 +1,25 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.replication.pull.api.exception; + +import com.google.gerrit.extensions.restapi.AuthException; + +public class UnauthorizedAuthException extends AuthException { + private static final long serialVersionUID = 1L; + + public UnauthorizedAuthException() { + super("Unauthorized access"); + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationITAbstract.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationITAbstract.java index 803a756..ba812e2 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationITAbstract.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationITAbstract.java
@@ -46,6 +46,7 @@ import org.eclipse.jgit.transport.PushResult; import org.eclipse.jgit.transport.RemoteRefUpdate; import org.eclipse.jgit.transport.RemoteRefUpdate.Status; +import org.junit.Ignore; import org.junit.Test; /** Base class to run regular and async acceptance tests */ @@ -345,7 +346,7 @@ }); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = TEST_REPLICATION_REMOTE) @GerritConfig(name = "container.replica", value = "true") public void shouldReplicateNewChangeRefToReplica() throws Exception {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionIT.java index 453a6b0..652daed 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionIT.java
@@ -22,6 +22,7 @@ import com.google.gerrit.extensions.restapi.Url; import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionData; import java.util.Optional; +import org.junit.Ignore; import org.junit.Test; public class ApplyObjectActionIT extends ActionITBase { @@ -71,7 +72,7 @@ assertHttpResponseCode(201)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") public void shouldAcceptPayloadWhenNodeIsAReplica() throws Exception { @@ -95,7 +96,7 @@ assertHttpResponseCode(201)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") public void shouldAcceptPayloadWhenNodeIsAReplicaAndProjectNameContainsSlash() throws Exception { @@ -122,7 +123,7 @@ assertHttpResponseCode(201)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") public void shouldReturnForbiddenWhenNodeIsAReplicaAndUSerIsAnonymous() throws Exception { @@ -187,7 +188,7 @@ assertHttpResponseCode(400)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") @GerritConfig(name = "auth.bearerToken", value = "some-bearer-token")
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java index 6ef5b2a..d0cd1b4 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ApplyObjectActionTest.java
@@ -35,6 +35,7 @@ import com.googlesource.gerrit.plugins.replication.pull.api.data.RevisionObjectData; import com.googlesource.gerrit.plugins.replication.pull.api.exception.MissingParentObjectException; import com.googlesource.gerrit.plugins.replication.pull.api.exception.RefUpdateException; +import com.googlesource.gerrit.plugins.replication.pull.api.exception.UnauthorizedAuthException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -90,7 +91,7 @@ @Mock FetchPreconditions preConditions; @Before - public void setup() { + public void setup() throws UnauthorizedAuthException { when(preConditions.canCallFetchApi()).thenReturn(true); applyObjectAction = new ApplyObjectAction(applyObjectCommand, deleteRefCommand, preConditions); @@ -124,12 +125,12 @@ @SuppressWarnings("cast") @Test - public void shouldReturnSourceUrlAndrefNameAsAResponseBody() throws Exception { + public void shouldReturnEmptyResponseBody() throws Exception { RevisionInput inputParams = new RevisionInput(label, refName, DUMMY_EVENT_TIMESTAMP, createSampleRevisionData()); Response<?> response = applyObjectAction.apply(projectResource, inputParams); - assertThat((RevisionInput) response.value()).isEqualTo(inputParams); + assertThat((String) response.value()).isEmpty(); } @Test(expected = BadRequestException.class)
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionIT.java index 0a69c3d..1ca013b 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionIT.java
@@ -18,11 +18,12 @@ import com.google.gerrit.entities.Project; import com.google.gerrit.entities.Project.NameKey; import com.google.gerrit.extensions.restapi.Url; +import org.junit.Ignore; import org.junit.Test; public class FetchActionIT extends ActionITBase { - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") public void shouldFetchRefWhenNodeIsAReplica() throws Exception { @@ -41,7 +42,7 @@ assertHttpResponseCode(201)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") public void shouldFetchRefWhenNodeIsAReplicaAndProjectNameContainsSlash() throws Exception { @@ -64,7 +65,7 @@ assertHttpResponseCode(201)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") public void shouldReturnForbiddenWhenNodeIsAReplicaAndUSerIsAnonymous() throws Exception { @@ -81,7 +82,7 @@ .execute(createRequest(sendObjectPayload), assertHttpResponseCode(403)); } - @Test + @Ignore @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") @GerritConfig(name = "container.replica", value = "true") @GerritConfig(name = "auth.bearerToken", value = "some-bearer-token")
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java index ce0b9d3..e7048f6 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java
@@ -33,6 +33,7 @@ import com.google.gerrit.server.git.WorkQueue.Task; import com.google.gerrit.server.project.ProjectResource; import com.googlesource.gerrit.plugins.replication.pull.api.exception.RemoteConfigurationMissingException; +import com.googlesource.gerrit.plugins.replication.pull.api.exception.UnauthorizedAuthException; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; @@ -66,7 +67,7 @@ @Mock FetchPreconditions preConditions; @Before - public void setup() { + public void setup() throws UnauthorizedAuthException { when(fetchJobFactory.create(any(), any(), any())).thenReturn(fetchJob); when(workQueue.getDefaultQueue()).thenReturn(exceutorService); when(urlFormatter.getRestUrl(anyString())).thenReturn(Optional.of(location));
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java index 2ed1466..9e5ca8d 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/PullReplicationFilterTest.java
@@ -50,7 +50,8 @@ String.format("any-prefix/projects/%s/%s~apply-object", PROJECT_NAME, PLUGIN_NAME); private final String APPLY_OBJECTS_URI = String.format("any-prefix/projects/%s/%s~apply-objects", PROJECT_NAME, PLUGIN_NAME); - private final String HEAD_URI = String.format("any-prefix/projects/%s/HEAD", PROJECT_NAME); + private final String HEAD_URI = + String.format("any-prefix/projects/%s/%s~HEAD", PROJECT_NAME, PLUGIN_NAME); private final String DELETE_PROJECT_URI = String.format("any-prefix/projects/%s/%s~delete-project", PROJECT_NAME, PLUGIN_NAME); private final String INIT_PROJECT_URI =
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadActionIT.java index f6e631f..9ceae5a 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadActionIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/UpdateHeadActionIT.java
@@ -16,6 +16,7 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow; +import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability; import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; import com.google.gerrit.acceptance.config.GerritConfig; @@ -25,19 +26,54 @@ import com.google.gerrit.extensions.api.projects.HeadInput; import com.google.gson.Gson; import com.google.inject.Inject; +import java.io.IOException; import javax.servlet.http.HttpServletResponse; -import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.auth.AuthenticationException; +import org.apache.http.client.ClientProtocolException; import org.junit.Ignore; import org.junit.Test; public class UpdateHeadActionIT extends ActionITBase { private static final Gson gson = newGson(); + private static final String PLUGIN_NAME = "pull-replication"; @Inject private ProjectOperations projectOperations; @Test @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") - public void shouldReturnUnauthorizedForUserWithoutPermissions() throws Exception { + public void shouldReturnForbiddenForUserWithoutPermissions() throws Exception { + shouldReturnForbiddenForUserWithoutPermissionsTest(); + } + + @Test + @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") + @GerritConfig(name = "container.replica", value = "true") + public void shouldReturnForbiddenForUserWithoutPermissionsInReplica() throws Exception { + shouldReturnForbiddenForUserWithoutPermissionsTest(); + } + + private void shouldReturnForbiddenForUserWithoutPermissionsTest() throws Exception { + httpClientFactory + .create(source) + .execute( + withBasicAuthenticationAsUser(createPutRequest(headInput("some/branch"))), + assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN)); + } + + @Test + @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") + public void shouldReturnUnauthorizedForAnonymousUser() throws Exception { + shouldReturnUnauthorizedForAnonymousUserTest(); + } + + @Test + @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") + @GerritConfig(name = "container.replica", value = "true") + public void shouldReturnUnauthorizedForAnonymousUserInReplica() throws Exception { + shouldReturnUnauthorizedForAnonymousUserTest(); + } + + private void shouldReturnUnauthorizedForAnonymousUserTest() throws Exception { httpClientFactory .create(source) .execute( @@ -106,6 +142,17 @@ @Test @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") public void shouldReturnForbiddenWhenMissingPermissions() throws Exception { + shouldReturnForbiddenWhenMissingPermissionsTest(); + } + + @Test + @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") + @GerritConfig(name = "container.replica", value = "true") + public void shouldReturnForbiddenWhenMissingPermissionsInReplica() throws Exception { + shouldReturnForbiddenWhenMissingPermissionsTest(); + } + + private void shouldReturnForbiddenWhenMissingPermissionsTest() throws Exception { httpClientFactory .create(source) .execute( @@ -115,18 +162,36 @@ @Test @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") - public void shouldReturnOKWhenRegisteredUserHasPermissions() throws Exception { - String testProjectName = project.get(); - String newBranch = "refs/heads/mybranch"; - String master = "refs/heads/master"; - BranchInput input = new BranchInput(); - input.revision = master; - gApi.projects().name(testProjectName).branch(newBranch).create(input); - HttpRequestBase put = withBasicAuthenticationAsUser(createPutRequest(headInput(newBranch))); + public void shouldReturnOKForUserWithPullReplicationCapability() throws Exception { + shouldReturnOKForUserWithPullReplicationCapabilityTest(); + } + + @Test + @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") + @GerritConfig(name = "container.replica", value = "true") + public void shouldReturnOKForUserWithPullReplicationCapabilityInReplica() throws Exception { + shouldReturnOKForUserWithPullReplicationCapabilityTest(); + } + + private void shouldReturnOKForUserWithPullReplicationCapabilityTest() + throws ClientProtocolException, IOException, AuthenticationException { + projectOperations + .allProjectsForUpdate() + .add( + allowCapability(PLUGIN_NAME + "-" + FetchApiCapability.CALL_FETCH_ACTION) + .group(REGISTERED_USERS)) + .update(); + httpClientFactory .create(source) - .execute(put, assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN)); + .execute( + withBasicAuthenticationAsUser(createPutRequest(headInput("refs/heads/master"))), + assertHttpResponseCode(HttpServletResponse.SC_OK)); + } + @Test + @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") + public void shouldReturnOKWhenRegisteredUserIsProjectOwner() throws Exception { projectOperations .project(project) .forUpdate() @@ -135,18 +200,9 @@ httpClientFactory .create(source) - .execute(put, assertHttpResponseCode(HttpServletResponse.SC_OK)); - } - - @Test - @GerritConfig(name = "gerrit.instanceId", value = "testInstanceId") - @GerritConfig(name = "container.replica", value = "true") - public void shouldReturnForbiddenWhenMissingPermissionsInReplica() throws Exception { - httpClientFactory - .create(source) .execute( - withBasicAuthenticationAsUser(createPutRequest(headInput("some/new/head"))), - assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN)); + withBasicAuthenticationAsUser(createPutRequest(headInput("refs/heads/master"))), + assertHttpResponseCode(HttpServletResponse.SC_OK)); } @Test @@ -203,6 +259,7 @@ @Override protected String getURLWithAuthenticationPrefix(String projectName) { - return String.format("%s/a/projects/%s/HEAD", adminRestSession.url(), projectName); + return String.format( + "%s/a/projects/%s/pull-replication~HEAD", adminRestSession.url(), projectName); } }