Enable configurable 'maxBatchChanges' limit

One use case is when a group is responsible for importing
large batches of changes delivered from external partners,
and those changes all require review. This group, and only
this group, should be allowed to bypass the limit that is
enforced for everyone else.

Allow site administrators to configure the 'maxBatchChanges'
limit for users from global capability UI of All-Projects
access. The min box does not make sense if its value is not 0,
so disable it after giving it the default value of 0.

The effective limit value will be the capability value if it
exists, or the value in gerrit.config if it exists, or else
no limit.

Change-Id: Ic929dc4a89cc8ccbd098035ce2ceac4f22fd54da
This commit is contained in:
Bruce Zu
2014-11-18 17:39:41 +08:00
committed by Dave Borowitz
parent 30c35c8398
commit 4512fe68ef
9 changed files with 61 additions and 6 deletions

View File

@@ -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

View File

@@ -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::

View File

@@ -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<String> NAMES_ALL;
private static final List<String> 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;
}

View File

@@ -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() {

View File

@@ -34,6 +34,7 @@ public class CapabilityCollection {
private final Map<String, List<PermissionRule>> permissions;
public final List<PermissionRule> administrateServer;
public final List<PermissionRule> batchChangesLimit;
public final List<PermissionRule> emailReviewers;
public final List<PermissionRule> priority;
public final List<PermissionRule> 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);

View File

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

View File

@@ -1485,7 +1485,8 @@ public class ReceiveCommits {
List<ChangeLookup> pending = Lists.newArrayList();
final Set<Change.Key> newChangeIds = new HashSet<>();
final int maxBatchChanges = receiveConfig.maxBatchChanges;
final int maxBatchChanges =
receiveConfig.getEffectiveMaxBatchChangesLimit(currentUser);
for (;;) {
final RevCommit c = walk.next();
if (c == null) {

View File

@@ -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;
}
}

View File

@@ -1,5 +1,6 @@
accessDatabase = Access Database
administrateServer = Administrate Server
batchChangesLimit = Batch Changes Limit
createAccount = Create Account
createGroup = Create Group
createProject = Create Project