Merge branch 'stable-3.1' into stable-3.2
* stable-3.1:
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
Change-Id: Ie26bdb0091ec83df53548f0de9718af0abf2b275
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 331c968..089ca92 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.common.data.GroupReference;
@@ -51,14 +53,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, "
@@ -80,6 +80,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";
@@ -91,6 +94,7 @@
private final PermissionBackend permissionBackend;
private final PluginConfigFactory cfg;
private final String pluginName;
+ private final Configuration config;
@Inject
public ProjectCreationValidator(
@@ -100,20 +104,27 @@
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));
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index ac9a12e..64af68d 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -23,4 +23,17 @@
label-Code-Review = -2..+2 group ${owner}
submit = group ${owner}
-```
\ No newline at end of file
+```
+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 f85ab27..0f434f7 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.common.data.GroupReference;
@@ -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