Merge branch 'stable-3.2-2021-07' * stable-3.2-2021-07: Hide repository name and description when user has no access Change-Id: Ibea3774aebdc41dd80169ee55d95002fec76b6ea
diff --git a/BUILD b/BUILD index e45eca3..08741ba 100644 --- a/BUILD +++ b/BUILD
@@ -1,5 +1,6 @@ load("//tools/bzl:genrule2.bzl", "genrule2") -load("//tools/bzl:plugin.bzl", "gerrit_plugin") +load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "gerrit_plugin") +load("//tools/bzl:junit.bzl", "junit_tests") gerrit_plugin( name = "gitiles", @@ -30,3 +31,16 @@ "zip -qr $$ROOT/$@ .", ]), ) + +junit_tests( + name = "gitiles_tests", + srcs = glob(["src/test/java/**/*Test.java"]), + tags = ["gitiles"], + visibility = ["//visibility:public"], + runtime_deps = [":gitiles__plugin"], + deps = PLUGIN_TEST_DEPS + PLUGIN_DEPS + [ + ":gitiles__plugin", + "//javatests/com/google/gerrit/util/http/testutil", + "//lib/gitiles", + ], +)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitiles/FilteredRepository.java b/src/main/java/com/googlesource/gerrit/plugins/gitiles/FilteredRepository.java index 218703e..29258f0 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitiles/FilteredRepository.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitiles/FilteredRepository.java
@@ -46,6 +46,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryBuilder; import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.transport.ServiceMayNotContinueException; class FilteredRepository extends Repository { static class Factory { @@ -72,6 +73,13 @@ if (!projectState.isPresent() || !projectState.get().statePermitsRead()) { throw new NoSuchProjectException(name); } + try { + permissionBackend.currentUser().project(name).check(ProjectPermission.ACCESS); + } catch (AuthException e) { + throw new NoSuchProjectException(name, e); + } catch (PermissionBackendException e) { + throw new ServiceMayNotContinueException(e); + } return new FilteredRepository( projectState.get(), userProvider.get(),
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitiles/Resolver.java b/src/main/java/com/googlesource/gerrit/plugins/gitiles/Resolver.java index 217dafc..71f604c 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitiles/Resolver.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitiles/Resolver.java
@@ -30,7 +30,7 @@ import org.eclipse.jgit.transport.resolver.RepositoryResolver; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; -class Resolver implements RepositoryResolver<HttpServletRequest> { +public class Resolver implements RepositoryResolver<HttpServletRequest> { private static final String NAME_KEY_ATTRIBUTE = Resolver.class.getName() + "/NameKey"; private final Provider<CurrentUser> userProvider;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/gitiles/ListProjectsAccessTest.java b/src/test/java/com/googlesource/gerrit/plugins/gitiles/ListProjectsAccessTest.java new file mode 100644 index 0000000..839bd26 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/gitiles/ListProjectsAccessTest.java
@@ -0,0 +1,101 @@ +// Copyright (C) 2021 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.gitiles; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow; +import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS; + +import com.google.common.collect.ImmutableSet; +import com.google.gerrit.acceptance.LightweightPluginDaemonTest; +import com.google.gerrit.acceptance.TestPlugin; +import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; +import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations; +import com.google.gerrit.entities.Permission; +import com.google.gerrit.entities.Project; +import com.google.gerrit.extensions.api.projects.BranchInput; +import com.google.gerrit.testing.ConfigSuite; +import com.google.gerrit.util.http.testutil.FakeHttpServletRequest; +import java.util.stream.Collectors; +import javax.inject.Inject; +import org.eclipse.jgit.lib.Config; +import org.junit.After; +import org.junit.Test; + +@TestPlugin(name = "gitiles", sysModule = "com.googlesource.gerrit.plugins.gitiles.Module") +public class ListProjectsAccessTest extends LightweightPluginDaemonTest { + @ConfigSuite.Default + public static Config defaultConfig() { + // Required config parameters to run Gitiles. + Config cfg = new Config(); + cfg.setString("gerrit", null, "gitHttpUrl", "http://example.com/gitiles"); + return cfg; + } + + @Inject private RequestScopeOperations requestScopeOperations; + @Inject private ProjectOperations projectOperations; + + @After + public void cleanUp() { + projectOperations.project(project).forUpdate().removeAllAccessSections().update(); + } + + @Test + public void listRepositories_repositoryVisibilityIsRespected() throws Exception { + projectOperations.allProjectsForUpdate().removeAllAccessSections().update(); + projectOperations.newProject().name("visible").create(); + projectOperations.newProject().name("invisible").create(); + projectOperations + .project(Project.nameKey("visible")) + .forUpdate() + .add(allow(Permission.READ).ref("refs/heads/main").group(ANONYMOUS_USERS)) + .update(); + requestScopeOperations.setApiUserAnonymous(); + + assertThat(access().listRepositories(null, ImmutableSet.of()).keySet()) + .containsExactly("visible"); + } + + @Test + public void listBranches_branchVisiblityIsRespected() throws Exception { + projectOperations.allProjectsForUpdate().removeAllAccessSections().update(); + projectOperations + .project(project) + .forUpdate() + .add(allow(Permission.READ).ref("refs/heads/visible").group(ANONYMOUS_USERS)) + .add(allow(Permission.CREATE).ref("refs/*").group(ANONYMOUS_USERS)) + .add(allow(Permission.PUSH).ref("refs/*").group(ANONYMOUS_USERS)) + .update(); + gApi.projects().name(project.get()).branch("refs/heads/visible").create(new BranchInput()); + gApi.projects().name(project.get()).branch("refs/heads/invisible").create(new BranchInput()); + requestScopeOperations.setApiUserAnonymous(); + + assertThat( + access() + .listRepositories( + null, ImmutableSet.of("refs/heads/visible", "refs/heads/invisible")) + .values().stream() + .map(r -> r.branches.keySet()) + .collect(Collectors.toList())) + .containsExactly(ImmutableSet.of("refs/heads/visible")); + } + + private GerritGitilesAccess access() { + return plugin + .getSysInjector() + .getInstance(GerritGitilesAccess.Factory.class) + .forRequest(new FakeHttpServletRequest()); + } +}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/gitiles/RepositoryResolverAccessTest.java b/src/test/java/com/googlesource/gerrit/plugins/gitiles/RepositoryResolverAccessTest.java new file mode 100644 index 0000000..dc0e89d --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/gitiles/RepositoryResolverAccessTest.java
@@ -0,0 +1,97 @@ +// Copyright (C) 2021 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.gitiles; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow; +import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS; +import static com.google.gerrit.testing.GerritJUnit.assertThrows; + +import com.google.gerrit.acceptance.LightweightPluginDaemonTest; +import com.google.gerrit.acceptance.TestPlugin; +import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; +import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations; +import com.google.gerrit.entities.Permission; +import com.google.gerrit.entities.Project; +import com.google.gerrit.extensions.api.projects.BranchInput; +import com.google.gerrit.testing.ConfigSuite; +import com.google.gerrit.util.http.testutil.FakeHttpServletRequest; +import javax.inject.Inject; +import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.eclipse.jgit.lib.Config; +import org.eclipse.jgit.lib.Repository; +import org.junit.After; +import org.junit.Test; + +@TestPlugin(name = "gitiles", sysModule = "com.googlesource.gerrit.plugins.gitiles.Module") +public class RepositoryResolverAccessTest extends LightweightPluginDaemonTest { + @ConfigSuite.Default + public static Config defaultConfig() { + // Required config parameters to run Gitiles. + Config cfg = new Config(); + cfg.setString("gerrit", null, "gitHttpUrl", "http://example.com/gitiles"); + return cfg; + } + + @Inject private RequestScopeOperations requestScopeOperations; + @Inject private ProjectOperations projectOperations; + + @After + public void cleanUp() { + projectOperations.project(project).forUpdate().removeAllAccessSections().update(); + } + + @Test + public void resolveRepository_branchVisibilityIsRespected() throws Exception { + projectOperations.allProjectsForUpdate().removeAllAccessSections().update(); + projectOperations + .project(project) + .forUpdate() + .add(allow(Permission.READ).ref("refs/heads/visible").group(ANONYMOUS_USERS)) + .add(allow(Permission.CREATE).ref("refs/*").group(ANONYMOUS_USERS)) + .add(allow(Permission.PUSH).ref("refs/*").group(ANONYMOUS_USERS)) + .update(); + gApi.projects().name(project.get()).branch("refs/heads/visible").create(new BranchInput()); + gApi.projects().name(project.get()).branch("refs/heads/invisible").create(new BranchInput()); + + Repository repo = resolver().open(new FakeHttpServletRequest(), project.get()); + assertThat(repo.exactRef("refs/heads/visible")).isNotNull(); + assertThat(repo.exactRef("refs/heads/invisible")).isNull(); + } + + @Test + public void resolveRepository_repositoryVisibilityIsRespected() throws Exception { + projectOperations.allProjectsForUpdate().removeAllAccessSections().update(); + projectOperations.newProject().name("visible").create(); + projectOperations.newProject().name("invisible").create(); + projectOperations + .project(Project.nameKey("visible")) + .forUpdate() + .add(allow(Permission.READ).ref("refs/heads/master").group(ANONYMOUS_USERS)) + .update(); + + requestScopeOperations.setApiUser(user.id()); + assertThat(resolver().open(new FakeHttpServletRequest(), "visible")).isNotNull(); + RepositoryNotFoundException ex = + assertThrows( + RepositoryNotFoundException.class, + () -> resolver().open(new FakeHttpServletRequest(), "invisible")); + assertThat(ex).hasMessageThat().contains("repository not found: invisible"); + } + + private Resolver resolver() { + return plugin.getSysInjector().getInstance(Resolver.class); + } +}