Merge branch 'stable-3.2' into stable-3.3
* stable-3.2:
Introduce an optional configuration to define a regex for naming rules
Upgrade bazlets to latest stable-3.1 to build with 3.1.12 API
Upgrade bazlets to latest stable-3.2 to build with 3.2.6 API
Upgrade bazlets to latest stable-3.1 to build with 3.1.11 API
Change-Id: Ic4e881927a5057b4209cac7d60d1bd8d9afccff4
diff --git a/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/Configuration.java b/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/Configuration.java
new file mode 100644
index 0000000..6a3c40f
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/Configuration.java
@@ -0,0 +1,57 @@
+// 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.ericsson.gerrit.plugins.projectgroupstructure;
+
+import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+class Configuration {
+ private static final Logger log = LoggerFactory.getLogger(Configuration.class);
+
+ private static final String NAME_REGEX = "nameRegex";
+ private static final String DEFAULT_NAME_REGEX_VALUE = ".+";
+ private static final String DEFAULT_NAME_REGEX_MESSAGE = "The value of the regex is invalid.";
+
+ static final String SEE_DOCUMENTATION_MSG = "\n\nSee documentation for more info: %s";
+ static final String DOCUMENTATION_PATH = "Documentation/index.html";
+
+ private String regexNameFilter;
+
+ @Inject
+ Configuration(
+ PluginConfigFactory pluginConfigFactory,
+ @PluginName String pluginName,
+ @PluginCanonicalWebUrl String url) {
+ PluginConfig config = pluginConfigFactory.getFromGerritConfig(pluginName);
+ regexNameFilter = config.getString(NAME_REGEX, DEFAULT_NAME_REGEX_VALUE);
+ if (!"/".matches(regexNameFilter) || " ".matches(regexNameFilter)) {
+ log.warn(
+ String.format(
+ DEFAULT_NAME_REGEX_MESSAGE + SEE_DOCUMENTATION_MSG, url + DOCUMENTATION_PATH));
+ regexNameFilter = DEFAULT_NAME_REGEX_VALUE;
+ }
+ }
+
+ public String getRegexNameFilter() {
+ return regexNameFilter;
+ }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidator.java b/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidator.java
index 2c50e81..9a71293 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidator.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidator.java
@@ -14,6 +14,8 @@
package com.ericsson.gerrit.plugins.projectgroupstructure;
+import static com.ericsson.gerrit.plugins.projectgroupstructure.Configuration.SEE_DOCUMENTATION_MSG;
+
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.google.gerrit.entities.AccountGroup;
@@ -52,14 +54,12 @@
private static final String AN_ERROR_OCCURRED_MSG =
"An error occurred while creating project, please contact Gerrit support";
- private static final String SEE_DOCUMENTATION_MSG = "\n\nSee documentation for more info: %s";
-
private static final String MUST_BE_OWNER_TO_CREATE_PROJECT_MSG =
"You must be owner of the parent project \"%s\" to create a nested project."
+ SEE_DOCUMENTATION_MSG;
private static final String PROJECT_CANNOT_CONTAINS_SPACES_MSG =
- "Project name cannot contains spaces." + SEE_DOCUMENTATION_MSG;
+ "Project name cannot contain spaces." + SEE_DOCUMENTATION_MSG;
private static final String ROOT_PROJECT_CANNOT_CONTAINS_SLASHES_MSG =
"Since the \"Rights Inherit From\" field is empty, "
@@ -81,6 +81,9 @@
private static final String PROJECT_MUST_START_WITH_PARENT_NAME_MSG =
"Project name must start with parent project name, e.g. %s." + SEE_DOCUMENTATION_MSG;
+ private static final String PROJECT_SHOULD_MATCH_REGEX_MSG =
+ "Project name should match the regex: %s." + SEE_DOCUMENTATION_MSG;
+
static final String DELEGATE_PROJECT_CREATION_TO = "delegateProjectCreationTo";
static final String DISABLE_GRANTING_PROJECT_OWNERSHIP = "disableGrantingProjectOwnership";
@@ -92,6 +95,7 @@
private final PermissionBackend permissionBackend;
private final PluginConfigFactory cfg;
private final String pluginName;
+ private final Configuration config;
@Inject
public ProjectCreationValidator(
@@ -101,20 +105,33 @@
Provider<CurrentUser> self,
PermissionBackend permissionBackend,
PluginConfigFactory cfg,
+ Configuration config,
@PluginName String pluginName) {
this.groups = groups;
- this.documentationUrl = url + "Documentation/index.html";
+ this.documentationUrl = url + Configuration.DOCUMENTATION_PATH;
this.allProjectsName = allProjectsName;
this.self = self;
this.permissionBackend = permissionBackend;
this.cfg = cfg;
this.pluginName = pluginName;
+ this.config = config;
}
@Override
public void validateNewProject(CreateProjectArgs args) throws ValidationException {
String name = args.getProjectName();
log.debug("validating creation of {}", name);
+ String regex = config.getRegexNameFilter();
+ if (!(name.matches(regex))) {
+ throw new ValidationException(
+ String.format(PROJECT_SHOULD_MATCH_REGEX_MSG, regex, documentationUrl));
+ }
+ if (name.contains(" ")) {
+ throw new ValidationException(
+ String.format(PROJECT_CANNOT_CONTAINS_SPACES_MSG, documentationUrl));
+ }
+
+ Project.NameKey newParent = args.newParent;
try {
permissionBackend.user(self.get()).check(GlobalPermission.ADMINISTRATE_SERVER);
@@ -134,8 +151,6 @@
String.format(PROJECT_CANNOT_CONTAINS_SPACES_MSG, documentationUrl));
}
- Project.NameKey newParent = args.newParent;
-
if (allProjectsName.get().equals(newParent)) {
validateRootProject(name, args.permissionsOnly);
} else {
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index de4c600..b9eb8aa 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -26,3 +26,17 @@
```
Note: default access rights configuration is bypassed for projects created by admins.
+
+Also, this plugin offers a way to restrict the new names of the projects to match an optionally
+configured regex in the gerrit.config. For example:
+
+```
+[plugin "@PLUGIN@"]
+ nameRegex = [a-z0-9/]+
+
+```
+
+In this example, the regex will limit the project created to non-capital letters, numbers
+and slashes. The regex must accept slash (/) to not disturb the functionality of the plugin.
+If the regex doesn't accept / or accepts spaces, it will be ignored and replaced with a default
+non-empty wildcard (.+) regex.
diff --git a/src/test/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidatorIT.java b/src/test/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidatorIT.java
index 226dc1b..d6394e5 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidatorIT.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/projectgroupstructure/ProjectCreationValidatorIT.java
@@ -24,6 +24,8 @@
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.TestPlugin;
+import com.google.gerrit.acceptance.UseLocalDisk;
+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.entities.AccountGroup;
@@ -47,6 +49,10 @@
@Inject private ProjectOperations projectOperations;
private static final String PLUGIN_NAME = "project-group-structure";
+ private static final String REGEX_INCLUDING_SLASH = "[a-z_/]+";
+ private static final String REGEX_NOT_INCLUDING_SLASH = "[a-z_]+";
+ private static final String REGEX_INCLUDING_SPACE = "[a-z_/ ]+";
+ private static final String PROJECT_WITH_SPACE = "project with space";
@Override
@Before
@@ -70,9 +76,44 @@
public void shouldProjectWithASpaceInTheirName() throws Exception {
ProjectInput in = new ProjectInput();
in.permissionsOnly = true;
- RestResponse r = userRestSession.put("/projects/" + Url.encode("project with space"), in);
+ RestResponse r = userRestSession.put("/projects/" + Url.encode(PROJECT_WITH_SPACE), in);
r.assertConflict();
- assertThat(r.getEntityContent()).contains("Project name cannot contains spaces");
+ assertThat(r.getEntityContent()).contains("Project name cannot contain spaces");
+ }
+
+ @Test
+ @UseLocalDisk
+ @GerritConfig(name = "project-group-structure.nameRegex", value = REGEX_INCLUDING_SPACE)
+ public void shouldRejectProjectWithSpaceInItsNameEvenWithRegex() throws Exception {
+ ProjectInput in = new ProjectInput();
+ in.permissionsOnly = true;
+ RestResponse r = userRestSession.put("/projects/" + Url.encode(PROJECT_WITH_SPACE), in);
+ r.assertConflict();
+ assertThat(r.getEntityContent()).contains("Project name cannot contain spaces");
+ }
+
+ @Test
+ @UseLocalDisk
+ @GerritConfig(name = "plugin.project-group-structure.nameRegex", value = REGEX_INCLUDING_SLASH)
+ public void shouldMatchProjectNameIfRegexContainsSlash() throws Exception {
+ ProjectInput in = new ProjectInput();
+ in.permissionsOnly = true;
+ RestResponse r = userRestSession.put("/projects/" + Url.encode("project1"), in);
+ userRestSession.put("/projects/" + Url.encode("project"), in).assertCreated();
+ r.assertConflict();
+ assertThat(r.getEntityContent())
+ .contains(String.format("Project name should match the regex: %s", REGEX_INCLUDING_SLASH));
+ }
+
+ @Test
+ @UseLocalDisk
+ @GerritConfig(
+ name = "plugin.project-group-structure.nameRegex",
+ value = REGEX_NOT_INCLUDING_SLASH)
+ public void shouldNotMatchProjectNameIfRegexMissesSlash() throws Exception {
+ ProjectInput in = new ProjectInput();
+ in.permissionsOnly = true;
+ userRestSession.put("/projects/" + Url.encode("PROJECT1"), in).assertCreated();
}
@Test