Allow project creation only when CREATE_PROJECT capability is set
Currently, the CREATE_PROJECT capability is not checked when creating
projects on primaries and replicas.
Bug: Issue 15279
Change-Id: Ifd0cfe78a8a3084ca250da4a795a4e66294f10fe
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java
index b7749da..01635e6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java
@@ -21,8 +21,12 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Url;
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.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -45,11 +49,16 @@
private final GerritConfigOps gerritConfigOps;
private final Provider<CurrentUser> userProvider;
+ private final PermissionBackend permissionBackend;
@Inject
- ProjectInitializationAction(GerritConfigOps gerritConfigOps, Provider<CurrentUser> userProvider) {
+ ProjectInitializationAction(
+ GerritConfigOps gerritConfigOps,
+ Provider<CurrentUser> userProvider,
+ PermissionBackend permissionBackend) {
this.gerritConfigOps = gerritConfigOps;
this.userProvider = userProvider;
+ this.permissionBackend = permissionBackend;
}
@Override
@@ -72,11 +81,19 @@
String path = httpServletRequest.getRequestURI();
String projectName = Url.decode(path.substring(path.lastIndexOf('/') + 1));
- if (initProject(projectName)) {
+ try {
+ if (initProject(projectName)) {
+ setResponse(
+ httpServletResponse,
+ HttpServletResponse.SC_CREATED,
+ "Project " + projectName + " initialized");
+ return;
+ }
+ } catch (AuthException | PermissionBackendException e) {
setResponse(
httpServletResponse,
- HttpServletResponse.SC_CREATED,
- "Project " + projectName + " initialized");
+ HttpServletResponse.SC_FORBIDDEN,
+ "User not authorized to create project " + projectName);
return;
}
@@ -86,7 +103,10 @@
"Cannot initialize project " + projectName);
}
- protected boolean initProject(String projectName) {
+ protected boolean initProject(String projectName)
+ throws AuthException, PermissionBackendException {
+ permissionBackend.user(userProvider.get()).check(GlobalPermission.CREATE_PROJECT);
+
Optional<URIish> maybeUri = gerritConfigOps.getGitRepositoryURI(projectName);
if (!maybeUri.isPresent()) {
logger.atSevere().log("Cannot initialize project '{}'", projectName);
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 9831704..a4ea953 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
@@ -163,7 +163,7 @@
}
private void doInitProject(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
- throws RestApiException, IOException {
+ throws RestApiException, IOException, PermissionBackendException {
String path = httpRequest.getRequestURI();
String projectName = Url.decode(path.substring(path.lastIndexOf('/') + 1));
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationActionIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationActionIT.java
index 4035fb8..ca4fa31 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationActionIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationActionIT.java
@@ -14,11 +14,16 @@
package com.googlesource.gerrit.plugins.replication.pull.api;
+import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import static com.googlesource.gerrit.plugins.replication.pull.api.ProjectInitializationAction.getProjectInitializationUrl;
import com.google.common.net.MediaType;
import com.google.gerrit.acceptance.config.GerritConfig;
+import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.restapi.Url;
+import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
@@ -27,6 +32,7 @@
public class ProjectInitializationActionIT extends ActionITBase {
public static final String INVALID_TEST_PROJECT_NAME = "\0";
+ @Inject private ProjectOperations projectOperations;
@Test
public void shouldReturnUnauthorizedForUserWithoutPermissions() throws Exception {
@@ -68,6 +74,43 @@
}
@Test
+ public void shouldCreateRepositoryWhenUserHasProjectCreationCapabilities() throws Exception {
+ String newProjectName = "new/newProjectForUserWithCapabilities";
+ url = getURL(newProjectName);
+ httpClientFactory
+ .create(source)
+ .execute(
+ createPutRequestWithHeaders(),
+ assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN),
+ getUserContext());
+
+ projectOperations
+ .project(allProjects)
+ .forUpdate()
+ .add(
+ allowCapability(GlobalCapability.CREATE_PROJECT)
+ .group(SystemGroupBackend.REGISTERED_USERS))
+ .update();
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ createPutRequestWithHeaders(),
+ assertHttpResponseCode(HttpServletResponse.SC_CREATED),
+ getUserContext());
+ }
+
+ @Test
+ public void shouldReturnForbiddenIfUserNotAuthorized() throws Exception {
+ httpClientFactory
+ .create(source)
+ .execute(
+ createPutRequestWithHeaders(),
+ assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN),
+ getUserContext());
+ }
+
+ @Test
@GerritConfig(name = "container.replica", value = "true")
public void shouldCreateRepositoryWhenNodeIsAReplica() throws Exception {
String newProjectName = "new/newProjectForReplica";
@@ -82,6 +125,46 @@
@Test
@GerritConfig(name = "container.replica", value = "true")
+ public void shouldReturnForbiddenIfUserNotAuthorizedAndNodeIsAReplica() throws Exception {
+ httpClientFactory
+ .create(source)
+ .execute(
+ createPutRequestWithHeaders(),
+ assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN),
+ getUserContext());
+ }
+
+ @Test
+ @GerritConfig(name = "container.replica", value = "true")
+ public void shouldCreateRepositoryWhenUserHasProjectCreationCapabilitiesAndNodeIsAReplica()
+ throws Exception {
+ String newProjectName = "new/newProjectForUserWithCapabilitiesReplica";
+ url = getURL(newProjectName);
+ httpClientFactory
+ .create(source)
+ .execute(
+ createPutRequestWithHeaders(),
+ assertHttpResponseCode(HttpServletResponse.SC_FORBIDDEN),
+ getUserContext());
+
+ projectOperations
+ .project(allProjects)
+ .forUpdate()
+ .add(
+ allowCapability(GlobalCapability.CREATE_PROJECT)
+ .group(SystemGroupBackend.REGISTERED_USERS))
+ .update();
+
+ httpClientFactory
+ .create(source)
+ .execute(
+ createPutRequestWithHeaders(),
+ assertHttpResponseCode(HttpServletResponse.SC_CREATED),
+ getUserContext());
+ }
+
+ @Test
+ @GerritConfig(name = "container.replica", value = "true")
public void shouldReturnInternalServerErrorIfProjectCannotBeCreatedWhenNodeIsAReplica()
throws Exception {
url = getURL(INVALID_TEST_PROJECT_NAME);