diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt index e814daf133..e500e4acb4 100644 --- a/Documentation/access-control.txt +++ b/Documentation/access-control.txt @@ -1158,6 +1158,20 @@ able to grant any access right to any group. They will also have all capabilities granted to them automatically. +[[capability_batchChangesLimit]] +=== Batch Changes Limit + +Allow site administrators to configure the batch changes limit for +users to override the system config +link:config-gerrit.html#receive.maxBatchChanges['receive.maxBatchChanges']. + +Administrators can add a global block to `All-Projects` with group(s) +that should have different limits. + +When applying a batch changes limit to a user the largest value +granted by any of their groups is used. 0 means no limit. + + [[capability_createAccount]] === Create Account diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index b99c8998a6..ccf27c66b5 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -2663,10 +2663,14 @@ Common unit suffixes of 'k', 'm', or 'g' are supported. The maximum number of changes that Gerrit allows to be pushed in a batch for review. When this number is exceeded Gerrit rejects the push with an error message. - ++ +May be overridden for certain groups by specifying a limit in the +link:access-control.html#capability_batchChangesLimit['Batch Changes Limit'] +global capability. ++ This setting can be used to prevent users from uploading large number of changes for review by mistake. - ++ Default is zero, no limit. [[receive.threadPoolSize]]receive.threadPoolSize:: diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java index e4b0381c0f..93fd208169 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java @@ -35,6 +35,9 @@ public class GlobalCapability { */ public static final String ADMINISTRATE_SERVER = "administrateServer"; + /** Maximum number of changes that may be pushed in a batch. */ + public static final String BATCH_CHANGES_LIMIT = "batchChangesLimit"; + /** Can create any account on the server. */ public static final String CREATE_ACCOUNT = "createAccount"; @@ -97,6 +100,13 @@ public class GlobalCapability { /** Can view all pending tasks in the queue (not just the filtered set). */ public static final String VIEW_QUEUE = "viewQueue"; + /** + * Default maximum number of changes that may be pushed in a batch, 0 means no + * limit. This is just used as a suggestion for prepopulating the field in the + * access UI. + */ + private static final int DEFAULT_MAX_BATCH_CHANGES = 0; + private static final List NAMES_ALL; private static final List NAMES_LC; @@ -104,6 +114,7 @@ public class GlobalCapability { NAMES_ALL = new ArrayList<>(); NAMES_ALL.add(ACCESS_DATABASE); NAMES_ALL.add(ADMINISTRATE_SERVER); + NAMES_ALL.add(BATCH_CHANGES_LIMIT); NAMES_ALL.add(CREATE_ACCOUNT); NAMES_ALL.add(CREATE_GROUP); NAMES_ALL.add(CREATE_PROJECT); @@ -140,7 +151,8 @@ public class GlobalCapability { /** @return true if the capability should have a range attached. */ public static boolean hasRange(String varName) { - return QUERY_LIMIT.equalsIgnoreCase(varName); + return QUERY_LIMIT.equalsIgnoreCase(varName) + || BATCH_CHANGES_LIMIT.equalsIgnoreCase(varName); } /** @return the valid range for the capability if it has one, otherwise null. */ @@ -151,6 +163,12 @@ public class GlobalCapability { 0, Integer.MAX_VALUE, 0, DEFAULT_MAX_QUERY_LIMIT); } + if (BATCH_CHANGES_LIMIT.equalsIgnoreCase(varName)) { + return new PermissionRange.WithDefaults( + varName, + 0, Integer.MAX_VALUE, + 0, DEFAULT_MAX_BATCH_CHANGES); + } return null; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java index 163702c07e..f66307ce14 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.java @@ -169,6 +169,10 @@ public class PermissionRuleEditor extends Composite implements deleteRule.removeFromParent(); deleteRule = null; } + + if (name.equals(GlobalCapability.BATCH_CHANGES_LIMIT)) { + min.setEnabled(false); + } } boolean isDeleted() { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java index f60c794400..3017f73cc1 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java @@ -34,6 +34,7 @@ public class CapabilityCollection { private final Map> permissions; public final List administrateServer; + public final List batchChangesLimit; public final List emailReviewers; public final List priority; public final List queryLimit; @@ -74,6 +75,7 @@ public class CapabilityCollection { permissions = Collections.unmodifiableMap(res); administrateServer = getPermission(GlobalCapability.ADMINISTRATE_SERVER); + batchChangesLimit = getPermission(GlobalCapability.BATCH_CHANGES_LIMIT); emailReviewers = getPermission(GlobalCapability.EMAIL_REVIEWERS); priority = getPermission(GlobalCapability.PRIORITY); queryLimit = getPermission(GlobalCapability.QUERY_LIMIT); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/CapabilityConstants.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/CapabilityConstants.java index 4c93ce03be..99a4f52875 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/CapabilityConstants.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/CapabilityConstants.java @@ -24,6 +24,7 @@ public class CapabilityConstants extends TranslationBundle { public String accessDatabase; public String administrateServer; + public String batchChangesLimit; public String createAccount; public String createGroup; public String createProject; diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java index b7c76792e8..585c072567 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java @@ -1485,7 +1485,8 @@ public class ReceiveCommits { List pending = Lists.newArrayList(); final Set newChangeIds = new HashSet<>(); - final int maxBatchChanges = receiveConfig.maxBatchChanges; + final int maxBatchChanges = + receiveConfig.getEffectiveMaxBatchChangesLimit(currentUser); for (;;) { final RevCommit c = walk.next(); if (c == null) { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveConfig.java index 6d37ae09e8..ac6116c7ac 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveConfig.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveConfig.java @@ -14,6 +14,9 @@ package com.google.gerrit.server.git; +import static com.google.gerrit.common.data.GlobalCapability.BATCH_CHANGES_LIMIT; + +import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.config.GerritServerConfig; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -25,7 +28,7 @@ class ReceiveConfig { final boolean checkMagicRefs; final boolean checkReferencedObjectsAreReachable; final boolean allowDrafts; - final int maxBatchChanges; + private final int systemMaxBatchChanges; @Inject ReceiveConfig(@GerritServerConfig Config config) { @@ -38,6 +41,13 @@ class ReceiveConfig { allowDrafts = config.getBoolean( "change", null, "allowDrafts", true); - maxBatchChanges = config.getInt("receive", "maxBatchChanges", 0); + systemMaxBatchChanges = config.getInt("receive", "maxBatchChanges", 0); + } + + public int getEffectiveMaxBatchChangesLimit(CurrentUser user) { + if (user.getCapabilities().canPerform(BATCH_CHANGES_LIMIT)) { + return user.getCapabilities().getRange(BATCH_CHANGES_LIMIT).getMax(); + } + return systemMaxBatchChanges; } } diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/config/CapabilityConstants.properties b/gerrit-server/src/main/resources/com/google/gerrit/server/config/CapabilityConstants.properties index c8e95bc0b2..9c48292403 100644 --- a/gerrit-server/src/main/resources/com/google/gerrit/server/config/CapabilityConstants.properties +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/config/CapabilityConstants.properties @@ -1,5 +1,6 @@ accessDatabase = Access Database administrateServer = Administrate Server +batchChangesLimit = Batch Changes Limit createAccount = Create Account createGroup = Create Group createProject = Create Project