Merge "Allows exception to the rules"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java
index cf6f31a..5f4df3d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java
@@ -59,8 +59,9 @@
import java.util.regex.Pattern;
public class BlockedKeywordValidator implements CommitValidationListener {
+ private static String KEY_CHECK_BLOCKED_KEYWORD = "blockedKeyword";
private static String KEY_CHECK_BLOCKED_KEYWORD_PATTERN =
- "blockedKeywordPattern";
+ KEY_CHECK_BLOCKED_KEYWORD + "Pattern";
public static AbstractModule module() {
return new AbstractModule() {
@@ -111,8 +112,9 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_CHECK_BLOCKED_KEYWORD)) {
ImmutableMap<String, Pattern> blockedKeywordPatterns =
patternCache.getAll(Arrays
.asList(cfg.getStringList(KEY_CHECK_BLOCKED_KEYWORD_PATTERN)));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java
index d137252..026cf7a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java
@@ -114,8 +114,9 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_BLOCKED_CONTENT_TYPE)) {
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
List<CommitValidationMessage> messages =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java
index 3a44758..8d9e2d1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java
@@ -171,8 +171,9 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_REJECT_DUPLICATE_PATHNAMES)) {
locale = getLocale(cfg);
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java
index 3e61ee6..4c13fdf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java
@@ -95,8 +95,9 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_BLOCKED_FILE_EXTENSION)) {
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
List<CommitValidationMessage> messages = performValidation(repo,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java
index 3c466d8..1b0e05b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java
@@ -81,8 +81,9 @@
receiveEvent.project.getNameKey(), pluginName);
String[] requiredFooters =
cfg.getStringList(KEY_REQUIRED_FOOTER);
- if (requiredFooters.length > 0 && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (requiredFooters.length > 0
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_REQUIRED_FOOTER)) {
List<CommitValidationMessage> messages = new LinkedList<>();
Set<String> footers = FluentIterable.from(receiveEvent.commit.getFooterLines())
.transform(new Function<FooterLine, String>() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java
index d912f5c..75daaf6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java
@@ -59,7 +59,8 @@
};
}
- public static String KEY_INVALID_FILENAME_PATTERN = "invalidFilenamePattern";
+ public static String KEY_INVALID_FILENAME = "invalidFilename";
+ public static String KEY_INVALID_FILENAME_PATTERN = KEY_INVALID_FILENAME + "Pattern";
private final String pluginName;
private final PluginConfigFactory cfgFactory;
@@ -87,8 +88,9 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_INVALID_FILENAME)) {
try (Repository repo = repoManager.openRepository(
receiveEvent.project.getNameKey())) {
List<CommitValidationMessage> messages =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java
index 8e50232..1c04334 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java
@@ -99,8 +99,9 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_CHECK_REJECT_WINDOWS_LINE_ENDINGS)) {
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
List<CommitValidationMessage> messages =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java
index f13d16b..5fb3637 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java
@@ -84,8 +84,9 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_MAX_PATH_LENGTH)) {
int maxPathLength = cfg.getInt(KEY_MAX_PATH_LENGTH, 0);
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java
index e1a492f..cb651fc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java
@@ -86,8 +86,9 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_CHECK_SUBMODULE)) {
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
List<CommitValidationMessage> messages =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java
index f3c4123..8a0e164 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java
@@ -87,8 +87,9 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (isActive(cfg) && validatorConfig.isEnabledForRef(
- receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ if (isActive(cfg)
+ && validatorConfig.isEnabledForRef(receiveEvent.getProjectNameKey(),
+ receiveEvent.getRefName(), KEY_CHECK_SYMLINK)) {
try (Repository repo =
repoManager.openRepository(receiveEvent.project.getNameKey())) {
List<CommitValidationMessage> messages =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
index 3a48288..5f02a69 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
@@ -15,64 +15,118 @@
package com.googlesource.gerrit.plugins.uploadvalidator;
import com.google.gerrit.common.data.RefConfigSection;
+import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.project.RefPatternMatcher;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
public class ValidatorConfig {
private static final Logger log = LoggerFactory
.getLogger(ValidatorConfig.class);
-
private final ConfigFactory configFactory;
+ private final Provider<CurrentUser> userProvider;
+ private final GroupCache groupCache;
@Inject
- public ValidatorConfig(ConfigFactory configFactory) {
+ public ValidatorConfig(ConfigFactory configFactory,
+ Provider<CurrentUser> userProvider, GroupCache groupCache) {
this.configFactory = configFactory;
+ this.userProvider = userProvider;
+ this.groupCache = groupCache;
}
- public boolean isEnabledForRef(Project.NameKey projectName, String refName) {
- PluginConfig pluginConfig = configFactory.get(projectName);
- if (pluginConfig == null) {
- log.error("Failed to check if validation is enabled for project "
- + projectName.get() + ": Plugin config not found");
- return false;
- }
- if(!isValidConfig(pluginConfig, projectName)) {
- return false;
- }
+ public boolean isEnabledForRef(Project.NameKey projectName, String refName,
+ String validatorOp) {
+ PluginConfig conf = configFactory.get(projectName);
- String[] refPatterns = pluginConfig.getStringList("ref");
- if (refPatterns.length == 0) {
- return true; // Default behavior: no branch-specific config
- }
-
- for (String refPattern : refPatterns) {
- if (match(refName, refPattern)) {
- return true;
- }
- }
- return false;
+ return conf != null
+ && isValidConfig(conf, projectName)
+ && (activeForRef(conf, refName))
+ && (!hasCriteria(conf, "skipGroup")
+ || !canSkipValidation(conf, validatorOp)
+ || !canSkipRef(conf, refName)
+ || !canSkipGroup(conf));
}
private boolean isValidConfig(PluginConfig config, Project.NameKey projectName) {
+ return hasValidConfigRef(config, "ref", projectName)
+ && hasValidConfigRef(config, "skipRef", projectName);
+ }
+
+ private boolean hasValidConfigRef(PluginConfig config, String refKey,
+ Project.NameKey projectName) {
boolean valid = true;
- for (String refPattern : config.getStringList("ref")) {
+ for (String refPattern : config.getStringList(refKey)) {
if (!RefConfigSection.isValid(refPattern)) {
log.error(
- "Invalid ref name/pattern/regex '{}' in {} project's plugin config",
- refPattern, projectName.get());
+ "Invalid {} name/pattern/regex '{}' in {} project's plugin config",
+ refKey, refPattern, projectName.get());
valid = false;
}
}
-
return valid;
}
- private static boolean match(String refName, String refPattern) {
- return RefPatternMatcher.getMatcher(refPattern).match(refName, null);
+ private boolean hasCriteria(PluginConfig config, String criteria) {
+ return config.getStringList(criteria).length > 0;
+ }
+
+ private boolean activeForRef(PluginConfig config, String ref) {
+ return matchCriteria(config, "ref", ref, true);
+ }
+
+ private boolean canSkipValidation(PluginConfig config, String validatorOp) {
+ return matchCriteria(config, "skipValidation", validatorOp, false);
+ }
+
+ private boolean canSkipRef(PluginConfig config, String ref) {
+ return matchCriteria(config, "skipRef", ref, true);
+ }
+
+ private boolean matchCriteria(PluginConfig config, String criteria,
+ String value, boolean allowRegex) {
+ boolean match = true;
+ for (String s : config.getStringList(criteria)) {
+ if ((allowRegex && match(value, s)) || (!allowRegex && s.equals(value))) {
+ return true;
+ }
+ match = false;
+ }
+ return match;
+ }
+
+ private static boolean match(String value, String pattern) {
+ return RefPatternMatcher.getMatcher(pattern).match(value, null);
+ }
+
+ private boolean canSkipGroup(PluginConfig conf) {
+ CurrentUser user = userProvider.get();
+ if (!user.isIdentifiedUser()) {
+ return false;
+ }
+
+ Stream<AccountGroup.UUID> skipGroups =
+ Arrays.stream(conf.getStringList("skipGroup")).map(this::groupUUID);
+ return user.asIdentifiedUser().getEffectiveGroups()
+ .containsAnyOf(skipGroups::iterator);
+ }
+
+ private AccountGroup.UUID groupUUID(String groupNameOrUUID) {
+ AccountGroup group =
+ groupCache.get(new AccountGroup.NameKey(groupNameOrUUID));
+ if (group == null) {
+ return new AccountGroup.UUID(groupNameOrUUID);
+ }
+ return group.getGroupUUID();
}
}
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index f958126..398a771 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -1,8 +1,5 @@
-@PLUGIN@
-========
-
-Configuration
--------------
+@PLUGIN@ Configuration
+======================
The configuration of the @PLUGIN@ plugin is done on project level in
the `project.config` file of the project.
@@ -227,3 +224,88 @@
ref = refs/heads/master
ref = ^refs/heads/stable-.*
```
+
+Permission to skip the rules
+----------------------------
+
+Some users may be allowed to skip some of the rules on a per project and
+per repository basis by configuring the appropriate "skip" settings in the
+project.config.
+
+Skip of the rules is controlled by:
+
+plugin.@PLUGIN@.skipGroup
+: Group names or UUIDs allowed to skip the rules.
+
+ Groups that are allowed to skip the rules.
+
+ Multiple values are supported.
+ Default: nobody is allowed to skip the rules (empty).
+
+ NOTE: When skipGroup isn't defined, all the other skip settings are ignored.
+
+plugin.@PLUGIN@.skipRef
+: Ref name, pattern or regexp of the branch to skip.
+
+ List of specific ref names, ref patterns, or regular expressions
+ of the branches where Groups defined in skipGroup are allowed to
+ skip the rules.
+
+ Multiple values are supported.
+ Default: skip validation on all branches for commits pushed by a member of
+ a group listed in skipGroup
+
+plugin.@PLUGIN@.skipValidation
+: Specific validation to be skipped.
+
+ List of specific validation operations allowed to be skipped by
+ the Groups defined in skipGroup on the branches defined in skipRef.
+
+ Validations can be one of the following strings:
+
+ - blockedContentType
+ - blockedFileExtension
+ - blockedKeyword
+ - invalidFilename
+ - maxPathLength
+ - rejectDuplicatePathnames
+ - rejectSubmodule
+ - rejectSymlink
+ - rejectWindowsLineEndings
+ - requiredFooter
+
+ Multiple values are supported.
+ Default: groups defined at skipGroup can skip all the validation rules.
+
+NOTE: Skip of the validations are inherited from parent projects. The definition
+of the skip criteria on All-Projects automatically apply to every project.
+
+The simplest configuration is to allow a specific group (e.g. Administrators)
+to skip all the rules:
+
+```
+ [plugin "@PLUGIN@"]
+ skipGroup = Administrators
+```
+
+A typical configuration would be to enable validation for a set of branches,
+while excluding a few of them.
+```
+ [plugin "@PLUGIN@"]
+ ref = ^refs/heads/stable-.*
+ skipGroup = release-manager
+ skipRef = refs/heads/stable-3.4
+ skipRef = refs/heads/stable-5.6
+```
+
+A more complex configuration is to allow a set of groups from LDAP, the ReleaseManager
+and GerritAdmins, to push any content to any file extension but only for the master branch:
+
+```
+ [plugin "@PLUGIN@"]
+ skipValidation = blockedFileExtension
+ skipValidation = blockedContentType
+ skipGroup = ldap/ReleaseManagers
+ skipGroup = ldap/GerritAdmins
+ skipRef = refs/heads/master
+```
\ No newline at end of file
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeGroupCacheUUIDByName.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeGroupCacheUUIDByName.java
new file mode 100644
index 0000000..8cefe93
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeGroupCacheUUIDByName.java
@@ -0,0 +1,70 @@
+// Copyright (C) 2017 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.uploadvalidator;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup.Id;
+import com.google.gerrit.reviewdb.client.AccountGroup.NameKey;
+import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
+import com.google.gerrit.server.account.GroupCache;
+
+import java.io.IOException;
+
+public class FakeGroupCacheUUIDByName implements GroupCache {
+ private AccountGroup accountGroup;
+
+ public FakeGroupCacheUUIDByName(AccountGroup accountGroup) {
+ this.accountGroup = accountGroup;
+ }
+
+ public FakeGroupCacheUUIDByName() {
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public AccountGroup get(Id groupId) {
+ return null;
+ }
+
+ @Override
+ public AccountGroup get(NameKey name) {
+ return accountGroup != null && accountGroup.getNameKey().equals(name)
+ ? accountGroup : null;
+ }
+
+ @Override
+ public AccountGroup get(UUID uuid) {
+ return null;
+ }
+
+ @Override
+ public ImmutableList<AccountGroup> all() {
+ return null;
+ }
+
+ @Override
+ public void onCreateGroup(NameKey newGroupName) throws IOException {
+ }
+
+ @Override
+ public void evict(AccountGroup group) throws IOException {
+ }
+
+ @Override
+ public void evictAfterRename(NameKey oldName, NameKey newName)
+ throws IOException {
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeGroupMembership.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeGroupMembership.java
new file mode 100644
index 0000000..9edec40
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeGroupMembership.java
@@ -0,0 +1,54 @@
+// Copyright (C) 2017 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.uploadvalidator;
+
+import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
+import com.google.gerrit.server.account.GroupMembership;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+public class FakeGroupMembership implements GroupMembership {
+ private final Set<String> memberOfGroup = new HashSet<>();
+
+ public FakeGroupMembership(String... memberOfGroup) {
+ this.memberOfGroup.addAll(Arrays.asList(memberOfGroup));
+ }
+
+ @Override
+ public boolean contains(UUID groupId) {
+ return memberOfGroup.contains(groupId.get());
+ }
+
+ @Override
+ public boolean containsAnyOf(Iterable<UUID> groupIds) {
+ return !intersection(groupIds).isEmpty();
+ }
+
+ @Override
+ public Set<UUID> intersection(Iterable<UUID> groupIds) {
+ return StreamSupport.stream(groupIds.spliterator(), false)
+ .filter(this::contains).collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<UUID> getKnownGroups() {
+ return new HashSet<>();
+ }
+
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeUserProvider.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeUserProvider.java
new file mode 100644
index 0000000..cd4f881
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeUserProvider.java
@@ -0,0 +1,44 @@
+// Copyright (C) 2017 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.uploadvalidator;
+
+import static org.easymock.EasyMock.*;
+
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Provider;
+
+public class FakeUserProvider implements Provider<CurrentUser> {
+ private final String[] groupUUID;
+
+ public FakeUserProvider(String... groupUUID) {
+ this.groupUUID = groupUUID;
+ }
+
+ @Override
+ public CurrentUser get() {
+ return createNew();
+ }
+
+ private IdentifiedUser createNew() {
+ IdentifiedUser user = createMock(IdentifiedUser.class);
+ expect(user.isIdentifiedUser()).andReturn(true);
+ expect(user.asIdentifiedUser()).andReturn(user);
+ expect(user.getEffectiveGroups()).andReturn(
+ new FakeGroupMembership(groupUUID));
+ replay(user);
+ return user;
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidatorTest.java
index b2421f0..0b8af8a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidatorTest.java
@@ -1,3 +1,17 @@
+// Copyright (C) 2017 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.uploadvalidator;
import static com.google.common.truth.Truth.assertThat;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java
index 962963b..42a2217 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java
@@ -14,9 +14,9 @@
package com.googlesource.gerrit.plugins.uploadvalidator;
-import com.google.gerrit.reviewdb.client.Project;
+import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.*;
+import com.google.gerrit.reviewdb.client.Project;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.junit.Test;
@@ -30,7 +30,9 @@
getConfig("[plugin \"uploadvalidator\"]\n"
+ "blockedFileExtension = jar");
- assertThat(config.isEnabledForRef(projectName, "anyRef")).isTrue();
+ assertThat(
+ config.isEnabledForRef(projectName, "anyRef", "blockedFileExtension"))
+ .isTrue();
}
@Test
@@ -40,8 +42,9 @@
+ " ref = refs/heads/anyref\n"
+ " blockedFileExtension = jar");
- assertThat(config.isEnabledForRef(projectName, "refs/heads/anyref"))
- .isTrue();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/anyref",
+ "blockedFileExtension")).isTrue();
}
@Test
@@ -51,8 +54,9 @@
+ " ref = anInvalidRef\n"
+ " blockedFileExtension = jar");
- assertThat(config.isEnabledForRef(projectName, "refs/heads/anyref"))
- .isFalse();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/anyref",
+ "blockedFileExtension")).isFalse();
}
@Test
@@ -62,10 +66,12 @@
+ " ref = ^refs/heads/mybranch.*\n"
+ " blockedFileExtension = jar");
- assertThat(config.isEnabledForRef(projectName, "refs/heads/anotherref"))
- .isFalse();
- assertThat(config.isEnabledForRef(projectName, "refs/heads/mybranch123"))
- .isTrue();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/anotherref",
+ "blockedFileExtension")).isFalse();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/mybranch123",
+ "blockedFileExtension")).isTrue();
}
@Test
@@ -76,18 +82,22 @@
+ " ref = refs/heads/branch2\n"
+ " blockedFileExtension = jar");
- assertThat(config.isEnabledForRef(projectName, "refs/heads/branch1"))
- .isTrue();
- assertThat(config.isEnabledForRef(projectName, "refs/heads/branch2"))
- .isTrue();
- assertThat(config.isEnabledForRef(projectName, "refs/heads/branch3"))
- .isFalse();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/branch1",
+ "blockedFileExtension")).isTrue();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/branch2",
+ "blockedFileExtension")).isTrue();
+ assertThat(
+ config.isEnabledForRef(projectName, "refs/heads/branch3",
+ "blockedFileExtension")).isFalse();
}
private ValidatorConfig getConfig(String defaultConfig)
throws ConfigInvalidException {
ValidatorConfig config =
- new ValidatorConfig(new FakeConfigFactory(projectName, defaultConfig));
+ new ValidatorConfig(new FakeConfigFactory(projectName, defaultConfig),
+ new FakeUserProvider(), new FakeGroupCacheUUIDByName());
return config;
}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/SkipValidationTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/SkipValidationTest.java
new file mode 100644
index 0000000..3718018
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/SkipValidationTest.java
@@ -0,0 +1,140 @@
+// Copyright (C) 2017 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.uploadvalidator;
+
+import static com.google.common.truth.Truth.assertThat;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+
+import com.google.gerrit.reviewdb.client.Project;
+
+import org.junit.Test;
+
+public class SkipValidationTest {
+ private Project.NameKey projectName = new Project.NameKey("testProject");
+
+ @Test
+ public void dontSkipByDefault() throws Exception {
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, ""),
+ new FakeUserProvider(), new FakeGroupCacheUUIDByName());
+
+ assertThat(validatorConfig.isEnabledForRef(projectName, "anyRef", "anyOp"))
+ .isTrue();
+ }
+
+ @Test
+ public void skipWhenUserBelongsToGroupUUID() throws Exception {
+ String config =
+ "[plugin \"uploadvalidator\"]\n"
+ + "skipValidation=testOp\n"
+ + "skipGroup=testGroup\n"
+ + "skipGroup=anotherGroup";
+
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, config),
+ new FakeUserProvider("testGroup", "yetAnotherGroup"),
+ new FakeGroupCacheUUIDByName());
+
+ assertThat(validatorConfig.isEnabledForRef(projectName, "anyRef", "testOp"))
+ .isFalse();
+ }
+
+ @Test
+ public void skipWhenUserBelongsToGroupName() throws Exception {
+ String config =
+ "[plugin \"uploadvalidator\"]\n"
+ + "skipValidation=testOp\n"
+ + "skipGroup=testGroupName\n";
+
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, config),
+ new FakeUserProvider("testGroupId"), new FakeGroupCacheUUIDByName(
+ new AccountGroup(new AccountGroup.NameKey("testGroupName"),
+ new AccountGroup.Id(1),
+ new AccountGroup.UUID("testGroupId"))));
+
+ assertThat(validatorConfig.isEnabledForRef(projectName, "anyRef", "testOp"))
+ .isFalse();
+ }
+
+ @Test
+ public void dontSkipWhenUserBelongsToOtherGroupsUUID() throws Exception {
+ String config =
+ "[plugin \"uploadvalidator\"]\n"
+ + "skipValidation=testOp\n"
+ + "skipGroup=testGroup\n"
+ + "skipGroup=anotherGroup";
+
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, config),
+ new FakeUserProvider("yetAnotherGroup"),
+ new FakeGroupCacheUUIDByName());
+
+ assertThat(validatorConfig.isEnabledForRef(projectName, "anyRef", "testOp"))
+ .isTrue();
+ }
+
+ @Test
+ public void dontSkipForOtherOps() throws Exception {
+ String config =
+ "[plugin \"uploadvalidator\"]\n"
+ + "skipValidation=testOp\n"
+ + "skipGroup=testGroup\n"
+ + "skipGroup=anotherGroup";
+
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, config),
+ new FakeUserProvider("testGroup", "yetAnotherGroup"),
+ new FakeGroupCacheUUIDByName());
+
+ assertThat(
+ validatorConfig.isEnabledForRef(projectName, "anyRef", "anotherOp"))
+ .isTrue();
+ }
+
+ @Test
+ public void skipOnlyOnSpecificRef() throws Exception {
+ String config =
+ "[plugin \"uploadvalidator\"]\n"
+ + "skipValidation=testOp\n"
+ + "skipRef=refs/heads/myref\n"
+ + "skipGroup=testGroup";
+
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, config),
+ new FakeUserProvider("testGroup"), new FakeGroupCacheUUIDByName());
+
+ assertThat(
+ validatorConfig.isEnabledForRef(projectName, "refs/heads/myref",
+ "testOp")).isFalse();
+ }
+
+ @Test
+ public void dontSkipOnOtherRefs() throws Exception {
+ String config =
+ "[plugin \"uploadvalidator\"]\n"
+ + "skipValidation=testOp\n"
+ + "skipRef=refs/heads/myref\n"
+ + "skipGroup=testGroup";
+
+ ValidatorConfig validatorConfig =
+ new ValidatorConfig(new FakeConfigFactory(projectName, config),
+ new FakeUserProvider("testGroup"), new FakeGroupCacheUUIDByName());
+
+ assertThat(
+ validatorConfig.isEnabledForRef(projectName, "refs/heads/anotherRef",
+ "testOp")).isTrue();
+ }
+}