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);