Merge branch 'stable-2.14' into stable-2.15

* stable-2.14:
  Elastic{Index|ReindexIT} Remove tests for 6.2 and 6.3
  ElasticVersionTest#version6: Add missing test for V6_4
  Allow more email RFC accepted chars in username
  Make inheritance of receive.maxObjectSizeLimit optional
  Allow to inherit receive.maxObjectSizeLimit from parent project
  CreateAccount: Simplify error message when username is invalid
  Bazel: Provide toolchain with activated error prone warnings
  Use ExternalId.isValidUsername instead of ExternalId.USER_NAME_PATTERN_REGEX
  Move regular expressions for user name from Account to ExternalId
  AccountIT: Add basic tests for creating user with {in}valid username
  Revert refactoring of Account.USER_NAME_PATTERN

Change-Id: Ie96721e9135fad25672dc1fd1599cd3394f20c33
This commit is contained in:
David Pursehouse 2018-09-06 16:24:38 +09:00
commit 5c9c11b709
32 changed files with 445 additions and 126 deletions

View File

@ -3635,6 +3635,14 @@ Default is zero.
+
Common unit suffixes of 'k', 'm', or 'g' are supported.
[[receive.inheritProjectMaxObjectSizeLimit]]receive.inheritProjectMaxObjectSizeLimit::
+
Controls whether the project-level link:config-project-config.html[`receive.maxObjectSizeLimit`]
value is inherited from the parent project. When `true`, the value is
inherited, otherwise it is not inherited.
+
Default is false, the value is not inherited.
[[receive.maxTrustDepth]]receive.maxTrustDepth::
+
If signed push validation is link:#receive.enableSignedPush[enabled],

View File

@ -144,8 +144,10 @@ The project specific setting in `project.config` may not set a value higher
than the global limit (if configured). In other words, it is only honored when
it further reduces the global limit.
+
The setting is not inherited from the parent project; it must be explicitly
set per project.
When link:config-gerrit.html#receive.inheritProjectMaxObjectSizeLimit[
`receive.inheritProjectmaxObjectSizeLimit`] is enabled in the global config,
the value is inherited from the parent project. Otherwise, it is not inherited
and must be explicitly set per project.
+
Default is zero.
+

View File

@ -121,6 +121,11 @@ The output JAR file will be be placed in:
Note that when building an individual plugin, the `core.zip` package
is not regenerated.
To build with all Error Prone warnings activated, run:
----
bazel build --java_toolchain //tools:error_prone_warnings_toolchain //...
----
[[IDEs]]

View File

@ -3061,10 +3061,10 @@ The max object size limit that is configured on the project as a
formatted string. +
Not set if there is no limit for the object size configured on project
level.
|`inherited_value` |optional|
The max object size limit that is inherited from the global config as a
formatted string. +
Not set if there is no global limit for the object size.
|`summary` |optional|
A string describing whether the value was inherited or overridden from
the parent project or global config. +
Not set if not inherited or overridden.
|===============================
[[project-access-input]]

View File

@ -1774,6 +1774,38 @@ public class AccountIT extends AbstractDaemonTest {
}
}
@Test
public void createUserWithValidUsername() throws Exception {
ImmutableList<String> names =
ImmutableList.of(
"user@domain",
"user-name",
"user_name",
"1234",
"user1234",
"1234@domain",
"user!+alias{*}#$%&^=~|@domain");
for (String name : names) {
gApi.accounts().create(name);
}
}
@Test
public void createUserWithInvalidUsername() throws Exception {
ImmutableList<String> invalidNames =
ImmutableList.of(
"@", "@foo", "-", "-foo", "_", "_foo", "!", "+", "{", "}", "*", "%", "#", "$", "&", "",
"^", "=", "~");
for (String name : invalidNames) {
try {
gApi.accounts().create(name);
fail(String.format("Expected BadRequestException for username [%s]", name));
} catch (BadRequestException e) {
assertThat(e).hasMessageThat().isEqualTo(String.format("Invalid username '%s'", name));
}
}
}
@Test
public void groups() throws Exception {
assertGroups(

View File

@ -16,6 +16,10 @@ package com.google.gerrit.acceptance.api.project;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.project.ProjectState.INHERITED_FROM_GLOBAL;
import static com.google.gerrit.server.project.ProjectState.INHERITED_FROM_PARENT;
import static com.google.gerrit.server.project.ProjectState.OVERRIDDEN_BY_GLOBAL;
import static com.google.gerrit.server.project.ProjectState.OVERRIDDEN_BY_PARENT;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
@ -215,7 +219,7 @@ public class ProjectIT extends AbstractDaemonTest {
ConfigInfo info = getConfig();
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@ -224,13 +228,30 @@ public class ProjectIT extends AbstractDaemonTest {
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isNull();
// Clear the value
info = setMaxObjectSize("0");
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@GerritConfig(name = "receive.inheritProjectMaxObjectSizeLimit", value = "true")
public void maxObjectSizeIsInheritedFromParentProject() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
info = getConfig(child);
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.summary)
.isEqualTo(String.format(INHERITED_FROM_PARENT, project));
}
@Test
@ -240,21 +261,75 @@ public class ProjectIT extends AbstractDaemonTest {
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isNull();
info = getConfig(child);
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.inheritedValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
public void maxObjectSizeOverridesParentProjectWhenNotSetOnParent() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = setMaxObjectSize("0");
assertThat(info.maxObjectSizeLimit.value).isNull();
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isNull();
info = setMaxObjectSize(child, "100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
public void maxObjectSizeOverridesParentProjectWhenLower() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = setMaxObjectSize("200k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
info = setMaxObjectSize(child, "100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@GerritConfig(name = "receive.inheritProjectMaxObjectSizeLimit", value = "true")
public void maxObjectSizeDoesNotOverrideParentProjectWhenHigher() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
info = setMaxObjectSize(child, "200k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.summary)
.isEqualTo(String.format(OVERRIDDEN_BY_PARENT, project));
}
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
public void maxObjectSizeIsInheritedFromGlobalConfig() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = getConfig();
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.summary).isEqualTo(INHERITED_FROM_GLOBAL);
info = getConfig(child);
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isEqualTo(INHERITED_FROM_GLOBAL);
}
@Test
@ -263,16 +338,40 @@ public class ProjectIT extends AbstractDaemonTest {
ConfigInfo info = setMaxObjectSize("100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "300k")
public void inheritedMaxObjectSizeOverridesGlobalConfigWhenLower() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = setMaxObjectSize("200k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
info = setMaxObjectSize(child, "100k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("102400");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("100k");
assertThat(info.maxObjectSizeLimit.summary).isNull();
}
@Test
@GerritConfig(name = "receive.maxObjectSizeLimit", value = "200k")
@GerritConfig(name = "receive.inheritProjectMaxObjectSizeLimit", value = "true")
public void maxObjectSizeDoesNotOverrideGlobalConfigWhenHigher() throws Exception {
Project.NameKey child = createProject(name("child"), project);
ConfigInfo info = setMaxObjectSize("300k");
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isEqualTo("300k");
assertThat(info.maxObjectSizeLimit.inheritedValue).isEqualTo("200k");
assertThat(info.maxObjectSizeLimit.summary).isEqualTo(OVERRIDDEN_BY_GLOBAL);
info = getConfig(child);
assertThat(info.maxObjectSizeLimit.value).isEqualTo("204800");
assertThat(info.maxObjectSizeLimit.configuredValue).isNull();
assertThat(info.maxObjectSizeLimit.summary).isEqualTo(OVERRIDDEN_BY_GLOBAL);
}
@Test
@ -308,9 +407,13 @@ public class ProjectIT extends AbstractDaemonTest {
}
private ConfigInfo setMaxObjectSize(String value) throws Exception {
return setMaxObjectSize(project, value);
}
private ConfigInfo setMaxObjectSize(Project.NameKey name, String value) throws Exception {
ConfigInput input = new ConfigInput();
input.maxObjectSizeLimit = value;
return setConfig(input);
return setConfig(name, input);
}
private ConfigInfo getConfig(Project.NameKey name) throws Exception {

View File

@ -47,17 +47,7 @@ public class ElasticReindexIT extends AbstractReindexTests {
}
@ConfigSuite.Config
public static Config elasticsearchV6_2() {
return getConfig(ElasticVersion.V6_2);
}
@ConfigSuite.Config
public static Config elasticsearchV6_3() {
return getConfig(ElasticVersion.V6_3);
}
@ConfigSuite.Config
public static Config elasticsearchV6_4() {
public static Config elasticsearchV6() {
return getConfig(ElasticVersion.V6_4);
}

View File

@ -46,17 +46,7 @@ public class ElasticIndexIT extends AbstractIndexTests {
}
@ConfigSuite.Config
public static Config elasticsearchV6_2() {
return getConfig(ElasticVersion.V6_2);
}
@ConfigSuite.Config
public static Config elasticsearchV6_3() {
return getConfig(ElasticVersion.V6_3);
}
@ConfigSuite.Config
public static Config elasticsearchV6_4() {
public static Config elasticsearchV6() {
return getConfig(ElasticVersion.V6_4);
}

View File

@ -54,6 +54,7 @@ public class ElasticVersionTest {
public void version6() throws Exception {
assertThat(ElasticVersion.V6_2.isV6()).isTrue();
assertThat(ElasticVersion.V6_3.isV6()).isTrue();
assertThat(ElasticVersion.V6_4.isV6()).isTrue();
assertThat(ElasticVersion.V5_6.isV6()).isFalse();
}
}

View File

@ -54,14 +54,17 @@ public class ConfigInfo {
}
public static class MaxObjectSizeLimitInfo {
/* The effective value. Null if not set. */
/** The effective value in bytes. Null if not set. */
@Nullable public String value;
/* The value configured on the project. Null if not set. */
/** The value configured explicitly on the project as a formatted string. Null if not set. */
@Nullable public String configuredValue;
/* The value configured globally. Null if not set. */
@Nullable public String inheritedValue;
/**
* Whether the value was inherited or overridden from the project's parent hierarchy or global
* config. Null if not inherited or overridden.
*/
@Nullable public String summary;
}
public static class ConfigParameterInfo {

View File

@ -23,7 +23,6 @@ import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.extensions.client.AccountFieldName;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
@ -38,6 +37,12 @@ import com.google.gwtexpui.globalkey.client.NpTextBox;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
class UsernameField extends Composite {
// If these regular expressions are modified the same modifications should be done to the
// corresponding regular expressions in the
// com.google.gerrit.server.account.ExternalId class.
private static final String USER_NAME_PATTERN_FIRST_REGEX = "[a-zA-Z0-9]";
private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9.!#$%&*+=?^_`\\{|\\}~@-]";
private CopyableLabel userNameLbl;
private NpTextBox userNameTxt;
private Button setUserName;
@ -185,9 +190,9 @@ class UsernameField extends Composite {
final TextBox box = (TextBox) event.getSource();
final String re;
if (box.getCursorPos() == 0) {
re = Account.USER_NAME_PATTERN_FIRST;
re = USER_NAME_PATTERN_FIRST_REGEX;
} else {
re = Account.USER_NAME_PATTERN_REST;
re = USER_NAME_PATTERN_REST_REGEX;
}
if (!String.valueOf(code).matches("^" + re + "$")) {
event.preventDefault();

View File

@ -36,8 +36,6 @@ public interface AdminMessages extends Messages {
String effectiveMaxObjectSizeLimit(String effectiveMaxObjectSizeLimit);
String globalMaxObjectSizeLimit(String globalMaxObjectSizeLimit);
String noMaxObjectSizeLimit();
String pluginProjectOptionsTitle(String pluginName);

View File

@ -6,7 +6,6 @@ deletedGroup = Deleted Group {0}
deletedReference = Reference {0} was deleted
deletedSection = Section {0} was deleted
effectiveMaxObjectSizeLimit = effective: {0} bytes
globalMaxObjectSizeLimit = The global max object size limit is set to {0}. The limit cannot be increased on project level.
noMaxObjectSizeLimit = No max object size limit is set.
pluginProjectOptionsTitle = {0} Plugin Options
pluginProjectOptionsTitle = {0} Plugin

View File

@ -432,9 +432,8 @@ public class ProjectInfoScreen extends ProjectScreen {
if (result.maxObjectSizeLimit().value() != null) {
effectiveMaxObjectSizeLimit.setText(
AdminMessages.I.effectiveMaxObjectSizeLimit(result.maxObjectSizeLimit().value()));
if (result.maxObjectSizeLimit().inheritedValue() != null) {
effectiveMaxObjectSizeLimit.setTitle(
AdminMessages.I.globalMaxObjectSizeLimit(result.maxObjectSizeLimit().inheritedValue()));
if (result.maxObjectSizeLimit().summary() != null) {
effectiveMaxObjectSizeLimit.setTitle(result.maxObjectSizeLimit().summary());
}
} else {
effectiveMaxObjectSizeLimit.setText(AdminMessages.I.noMaxObjectSizeLimit());

View File

@ -173,10 +173,10 @@ public class ConfigInfo extends JavaScriptObject {
public static class MaxObjectSizeLimitInfo extends JavaScriptObject {
public final native String value() /*-{ return this.value; }-*/;
public final native String inheritedValue() /*-{ return this.inherited_value; }-*/;
public final native String configuredValue() /*-{ return this.configured_value }-*/;
public final native String summary() /*-{ return this.summary; }-*/;
protected MaxObjectSizeLimitInfo() {}
}

View File

@ -16,7 +16,6 @@ gwt_module(
visibility = ["//visibility:public"],
deps = [
"//gerrit-extension-api:client",
"//lib:guava",
"//lib:gwtorm-client",
"//lib:gwtorm-client_src",
],

View File

@ -18,13 +18,11 @@ import static com.google.gerrit.reviewdb.client.RefNames.REFS_DRAFT_COMMENTS;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_STARRED_CHANGES;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_USERS;
import com.google.common.annotations.GwtIncompatible;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.IntKey;
import java.sql.Timestamp;
import java.util.regex.Pattern;
/**
* Information about a single user.
@ -48,31 +46,6 @@ import java.util.regex.Pattern;
* </ul>
*/
public final class Account {
private static final String USER_NAME_COMMON_PATTERN = "a-zA-Z0-9";
public static final String USER_NAME_PATTERN_FIRST = "[" + USER_NAME_COMMON_PATTERN + "]";
public static final String USER_NAME_PATTERN_REST = "[" + USER_NAME_COMMON_PATTERN + "._@-]";
public static final String USER_NAME_PATTERN_LAST = USER_NAME_PATTERN_FIRST;
/** Regular expression that {@link #userName} must match. */
public static final String USER_NAME_PATTERN =
"^("
+ //
USER_NAME_PATTERN_FIRST
+ //
USER_NAME_PATTERN_REST
+ "*"
+ //
USER_NAME_PATTERN_LAST
+ //
"|"
+ //
USER_NAME_PATTERN_FIRST
+ //
")$";
@GwtIncompatible("Unemulated class java.util.regex.Pattern")
public static final Pattern USER_NAME_PATTERN_COMPILED = Pattern.compile(USER_NAME_PATTERN);
/** Key local to Gerrit to identify a user. */
public static class Id extends IntKey<com.google.gwtorm.client.Key<?>> {
private static final long serialVersionUID = 1L;

View File

@ -14,10 +14,10 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.reviewdb.client.Account.USER_NAME_PATTERN_COMPILED;
import static java.util.stream.Collectors.toSet;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@ -110,7 +110,7 @@ public class AccountResolver {
return Collections.emptySet();
}
if (USER_NAME_PATTERN_COMPILED.matcher(nameOrEmail).matches()) {
if (ExternalId.isValidUsername(nameOrEmail)) {
AccountState who = byId.getByUsername(nameOrEmail);
if (who != null) {
return Collections.singleton(who.getAccount().getId());

View File

@ -14,7 +14,6 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.reviewdb.client.Account.USER_NAME_PATTERN_COMPILED;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME;
import com.google.gerrit.common.Nullable;
@ -82,7 +81,7 @@ public class ChangeUserName implements Callable<VoidResult> {
ExternalIdsUpdate externalIdsUpdate = externalIdsUpdateFactory.create();
if (newUsername != null && !newUsername.isEmpty()) {
if (!USER_NAME_PATTERN_COMPILED.matcher(newUsername).matches()) {
if (!ExternalId.isValidUsername(newUsername)) {
throw new InvalidUserNameException();
}

View File

@ -14,8 +14,6 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.reviewdb.client.Account.USER_NAME_PATTERN;
import static com.google.gerrit.reviewdb.client.Account.USER_NAME_PATTERN_COMPILED;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAILTO;
import com.google.gerrit.common.Nullable;
@ -122,9 +120,8 @@ public class CreateAccount implements RestModifyView<TopLevelResource, AccountIn
throw new BadRequestException("username must match URL");
}
if (!USER_NAME_PATTERN_COMPILED.matcher(username).matches()) {
throw new BadRequestException(
"Username '" + username + "' must comply with [" + USER_NAME_PATTERN + "] pattern.");
if (!ExternalId.isValidUsername(username)) {
throw new BadRequestException("Invalid username '" + username + "'");
}
Set<AccountGroup.UUID> groups = parseGroups(input.groups);

View File

@ -14,12 +14,7 @@
package com.google.gerrit.server.account;
import com.google.gerrit.reviewdb.client.Account;
/**
* Error indicating the SSH user name does not match {@link Account#USER_NAME_PATTERN_COMPILED}
* pattern.
*/
/** Error indicating the SSH user name does not match the expected pattern. */
public class InvalidUserNameException extends Exception {
private static final long serialVersionUID = 1L;

View File

@ -30,6 +30,7 @@ import com.google.gerrit.server.account.HashedPassword;
import java.io.Serializable;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
@ -37,6 +38,36 @@ import org.eclipse.jgit.lib.ObjectId;
@AutoValue
public abstract class ExternalId implements Serializable {
// If these regular expressions are modified the same modifications should be done to the
// corresponding regular expressions in the
// com.google.gerrit.client.account.UsernameField class.
private static final String USER_NAME_PATTERN_FIRST_REGEX = "[a-zA-Z0-9]";
private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9.!#$%&*+=?^_`\\{|\\}~@-]";
private static final String USER_NAME_PATTERN_LAST_REGEX = "[a-zA-Z0-9]";
/** Regular expression that a username must match. */
private static final String USER_NAME_PATTERN_REGEX =
"^("
+ //
USER_NAME_PATTERN_FIRST_REGEX
+ //
USER_NAME_PATTERN_REST_REGEX
+ "*"
+ //
USER_NAME_PATTERN_LAST_REGEX
+ //
"|"
+ //
USER_NAME_PATTERN_FIRST_REGEX
+ //
")$";
private static final Pattern USER_NAME_PATTERN = Pattern.compile(USER_NAME_PATTERN_REGEX);
public static boolean isValidUsername(String username) {
return USER_NAME_PATTERN.matcher(username).matches();
}
private static final long serialVersionUID = 1L;
private static final String EXTERNAL_ID_SECTION = "externalId";

View File

@ -14,14 +14,13 @@
package com.google.gerrit.server.args4j;
import static com.google.gerrit.reviewdb.client.Account.USER_NAME_PATTERN_COMPILED;
import com.google.gerrit.extensions.client.AuthType;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@ -92,7 +91,7 @@ public class AccountIdHandler extends OptionHandler<Account.Id> {
}
private Account.Id createAccountByLdap(String user) throws CmdLineException, IOException {
if (!USER_NAME_PATTERN_COMPILED.matcher(user).matches()) {
if (!ExternalId.isValidUsername(user)) {
throw new CmdLineException(owner, "user \"" + user + "\" not found");
}

View File

@ -28,6 +28,7 @@ public class TransferConfig {
private final PackConfig packConfig;
private final long maxObjectSizeLimit;
private final String maxObjectSizeLimitFormatted;
private final boolean inheritProjectMaxObjectSizeLimit;
@Inject
TransferConfig(@GerritServerConfig Config cfg) {
@ -42,6 +43,8 @@ public class TransferConfig {
TimeUnit.SECONDS);
maxObjectSizeLimit = cfg.getLong("receive", "maxObjectSizeLimit", 0);
maxObjectSizeLimitFormatted = cfg.getString("receive", null, "maxObjectSizeLimit");
inheritProjectMaxObjectSizeLimit =
cfg.getBoolean("receive", "inheritProjectMaxObjectSizeLimit", false);
packConfig = new PackConfig();
packConfig.setDeltaCompress(false);
@ -65,4 +68,8 @@ public class TransferConfig {
public String getFormattedMaxObjectSizeLimit() {
return maxObjectSizeLimitFormatted;
}
public boolean getInheritProjectMaxObjectSizeLimit() {
return inheritProjectMaxObjectSizeLimit;
}
}

View File

@ -215,7 +215,7 @@ public class AsyncReceiveCommits implements PreReceiveHook {
rp.setAllowNonFastForwards(true);
rp.setRefLogIdent(user.newRefLogIdent());
rp.setTimeout(transferConfig.getTimeout());
rp.setMaxObjectSizeLimit(state.getEffectiveMaxObjectSizeLimit());
rp.setMaxObjectSizeLimit(state.getEffectiveMaxObjectSizeLimit().value);
rp.setCheckReceivedObjects(state.getConfig().getCheckReceivedObjects());
rp.setRefFilter(new ReceiveRefFilter());
rp.setAllowPushOptions(true);

View File

@ -14,8 +14,6 @@
package com.google.gerrit.server.group;
import static com.google.gerrit.reviewdb.client.Account.USER_NAME_PATTERN_COMPILED;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
@ -40,6 +38,7 @@ import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountsCollection;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.group.AddMembers.Input;
import com.google.gwtorm.server.OrmException;
@ -183,7 +182,7 @@ public class AddMembers implements RestModifyView<GroupResource, Input> {
}
private Account createAccountByLdap(String user) throws IOException {
if (!USER_NAME_PATTERN_COMPILED.matcher(user).matches()) {
if (!ExternalId.isValidUsername(user)) {
return null;
}

View File

@ -30,7 +30,7 @@ import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.project.ProjectState.EffectiveMaxObjectSizeLimit;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
@ -40,7 +40,6 @@ public class ConfigInfoImpl extends ConfigInfo {
public ConfigInfoImpl(
boolean serverEnableSignedPush,
ProjectControl control,
TransferConfig transferConfig,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
AllProjectsName allProjects,
@ -114,7 +113,7 @@ public class ConfigInfoImpl extends ConfigInfo {
this.privateByDefault = privateByDefault;
this.workInProgressByDefault = workInProgressByDefault;
this.maxObjectSizeLimit = getMaxObjectSizeLimit(projectState, transferConfig, p);
this.maxObjectSizeLimit = getMaxObjectSizeLimit(projectState, p);
this.submitType = p.getSubmitType();
this.state =
@ -139,13 +138,13 @@ public class ConfigInfoImpl extends ConfigInfo {
this.extensionPanelNames = projectState.getConfig().getExtensionPanelSections();
}
private MaxObjectSizeLimitInfo getMaxObjectSizeLimit(
ProjectState projectState, TransferConfig transferConfig, Project p) {
private MaxObjectSizeLimitInfo getMaxObjectSizeLimit(ProjectState projectState, Project p) {
MaxObjectSizeLimitInfo info = new MaxObjectSizeLimitInfo();
long value = projectState.getEffectiveMaxObjectSizeLimit();
EffectiveMaxObjectSizeLimit limit = projectState.getEffectiveMaxObjectSizeLimit();
long value = limit.value;
info.value = value == 0 ? null : String.valueOf(value);
info.configuredValue = p.getMaxObjectSizeLimit();
info.inheritedValue = transferConfig.getFormattedMaxObjectSizeLimit();
info.summary = limit.summary;
return info;
}

View File

@ -23,14 +23,12 @@ import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.TransferConfig;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class GetConfig implements RestReadView<ProjectResource> {
private final boolean serverEnableSignedPush;
private final TransferConfig transferConfig;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
private final PluginConfigFactory cfgFactory;
private final AllProjectsName allProjects;
@ -40,14 +38,12 @@ public class GetConfig implements RestReadView<ProjectResource> {
@Inject
public GetConfig(
@EnableSignedPush boolean serverEnableSignedPush,
TransferConfig transferConfig,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
AllProjectsName allProjects,
UiActions uiActions,
DynamicMap<RestView<ProjectResource>> views) {
this.serverEnableSignedPush = serverEnableSignedPush;
this.transferConfig = transferConfig;
this.pluginConfigEntries = pluginConfigEntries;
this.allProjects = allProjects;
this.cfgFactory = cfgFactory;
@ -60,7 +56,6 @@ public class GetConfig implements RestReadView<ProjectResource> {
return new ConfigInfoImpl(
serverEnableSignedPush,
resource.getControl(),
transferConfig,
pluginConfigEntries,
cfgFactory,
allProjects,

View File

@ -17,6 +17,7 @@ package com.google.gerrit.server.project;
import static com.google.gerrit.common.data.PermissionRule.Action.ALLOW;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@ -97,6 +98,7 @@ public class ProjectState {
private final Map<String, ProjectLevelConfig> configs;
private final Set<AccountGroup.UUID> localOwners;
private final long globalMaxObjectSizeLimit;
private final boolean inheritProjectMaxObjectSizeLimit;
/** Prolog rule state. */
private volatile PrologMachineCopy rulesMachine;
@ -147,6 +149,7 @@ public class ProjectState {
? limitsFactory.create(config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES))
: null;
this.globalMaxObjectSizeLimit = transferConfig.getMaxObjectSizeLimit();
this.inheritProjectMaxObjectSizeLimit = transferConfig.getInheritProjectMaxObjectSizeLimit();
if (isAllProjects && !Permission.canBeOnAllProjects(AccessSection.ALL, Permission.OWNER)) {
localOwners = Collections.emptySet();
@ -258,13 +261,58 @@ public class ProjectState {
return cfg;
}
public long getEffectiveMaxObjectSizeLimit() {
long local = config.getMaxObjectSizeLimit();
if (globalMaxObjectSizeLimit > 0 && local > 0) {
return Math.min(globalMaxObjectSizeLimit, local);
public static class EffectiveMaxObjectSizeLimit {
public long value;
public String summary;
}
private static final String MAY_NOT_SET = "This project may not set a higher limit.";
@VisibleForTesting
public static final String INHERITED_FROM_PARENT = "Inherited from parent project '%s'.";
@VisibleForTesting
public static final String OVERRIDDEN_BY_PARENT =
"Overridden by parent project '%s'. " + MAY_NOT_SET;
@VisibleForTesting
public static final String INHERITED_FROM_GLOBAL = "Inherited from the global config.";
@VisibleForTesting
public static final String OVERRIDDEN_BY_GLOBAL =
"Overridden by the global config. " + MAY_NOT_SET;
public EffectiveMaxObjectSizeLimit getEffectiveMaxObjectSizeLimit() {
EffectiveMaxObjectSizeLimit result = new EffectiveMaxObjectSizeLimit();
result.value = config.getMaxObjectSizeLimit();
if (inheritProjectMaxObjectSizeLimit) {
for (ProjectState parent : parents()) {
long parentValue = parent.config.getMaxObjectSizeLimit();
if (parentValue > 0 && result.value > 0) {
if (parentValue < result.value) {
result.value = parentValue;
result.summary = String.format(OVERRIDDEN_BY_PARENT, parent.config.getName());
}
} else if (parentValue > 0) {
result.value = parentValue;
result.summary = String.format(INHERITED_FROM_PARENT, parent.config.getName());
}
}
}
// zero means "no limit", in this case the max is more limiting
return Math.max(globalMaxObjectSizeLimit, local);
if (globalMaxObjectSizeLimit > 0 && result.value > 0) {
if (globalMaxObjectSizeLimit < result.value) {
result.value = globalMaxObjectSizeLimit;
result.summary = OVERRIDDEN_BY_GLOBAL;
}
} else if (globalMaxObjectSizeLimit > result.value) {
// zero means "no limit", in this case the max is more limiting
result.value = globalMaxObjectSizeLimit;
result.summary = INHERITED_FROM_GLOBAL;
}
return result;
}
/** Get the sections that pertain only to this project. */

View File

@ -39,7 +39,6 @@ import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.TransferConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@ -61,7 +60,6 @@ public class PutConfig implements RestModifyView<ProjectResource, ConfigInput> {
private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
private final ProjectCache projectCache;
private final ProjectState.Factory projectStateFactory;
private final TransferConfig transferConfig;
private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
private final PluginConfigFactory cfgFactory;
private final AllProjectsName allProjects;
@ -75,7 +73,6 @@ public class PutConfig implements RestModifyView<ProjectResource, ConfigInput> {
Provider<MetaDataUpdate.User> metaDataUpdateFactory,
ProjectCache projectCache,
ProjectState.Factory projectStateFactory,
TransferConfig transferConfig,
DynamicMap<ProjectConfigEntry> pluginConfigEntries,
PluginConfigFactory cfgFactory,
AllProjectsName allProjects,
@ -86,7 +83,6 @@ public class PutConfig implements RestModifyView<ProjectResource, ConfigInput> {
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.projectCache = projectCache;
this.projectStateFactory = projectStateFactory;
this.transferConfig = transferConfig;
this.pluginConfigEntries = pluginConfigEntries;
this.cfgFactory = cfgFactory;
this.allProjects = allProjects;
@ -197,7 +193,6 @@ public class PutConfig implements RestModifyView<ProjectResource, ConfigInput> {
return new ConfigInfoImpl(
serverEnableSignedPush,
state.controlFor(user.get()),
transferConfig,
pluginConfigEntries,
cfgFactory,
allProjects,

@ -1 +1 @@
Subproject commit 578bc671ec38eba7c2aab38644fd1c4deacad4dd
Subproject commit 64032d745bf818201f0d41dfb8a355d15e1bdc9f

View File

@ -1,6 +1,154 @@
load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")
py_binary(
name = "merge_jars",
srcs = ["merge_jars.py"],
main = "merge_jars.py",
visibility = ["//visibility:public"],
)
# TODO(davido): remove this when minimum suported Bazel version >= 0.17
# Copied from tools/jdk/default_java_toolchain.bzl to make Bazel 0.16
# and later Bazel released to work as expected. See this issue for context:
# https://github.com/bazelbuild/bazel/issues/6009
JDK9_JVM_OPTS = [
# Allow JavaBuilder to access internal javac APIs.
"--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
# override the javac in the JDK.
"--patch-module=java.compiler=$(location @bazel_tools//third_party/java/jdk/langtools:java_compiler_jar)",
"--patch-module=jdk.compiler=$(location @bazel_tools//third_party/java/jdk/langtools:jdk_compiler_jar)",
# quiet warnings from com.google.protobuf.UnsafeUtil,
# see: https://github.com/google/protobuf/issues/3781
"--add-opens=java.base/java.nio=ALL-UNNAMED",
]
# See https://github.com/bazelbuild/bazel/issues/3427 for more context
default_java_toolchain(
name = "error_prone_warnings_toolchain_bazel_0.16",
bootclasspath = ["@bazel_tools//tools/jdk:platformclasspath.jar"],
jvm_opts = JDK9_JVM_OPTS,
package_configuration = [
":error_prone",
],
visibility = ["//visibility:public"],
)
default_java_toolchain(
name = "error_prone_warnings_toolchain",
bootclasspath = ["@bazel_tools//tools/jdk:platformclasspath8.jar"],
package_configuration = [
":error_prone",
],
visibility = ["//visibility:public"],
)
# This EP warnings list is based on:
# https://github.com/bazelbuild/BUILD_file_generator/blob/master/tools/bazel_defs/java.bzl
java_package_configuration(
name = "error_prone",
javacopts = [
"-XepDisableWarningsInGeneratedCode",
"-Xep:MissingCasesInEnumSwitch:ERROR",
"-Xep:ReferenceEquality:WARN",
"-Xep:StringEquality:WARN",
"-Xep:WildcardImport:WARN",
"-Xep:AmbiguousMethodReference:WARN",
"-Xep:BadAnnotationImplementation:WARN",
"-Xep:BadComparable:WARN",
"-Xep:BoxedPrimitiveConstructor:ERROR",
"-Xep:CannotMockFinalClass:WARN",
"-Xep:ClassCanBeStatic:WARN",
"-Xep:ClassNewInstance:WARN",
"-Xep:DefaultCharset:WARN",
"-Xep:DoubleCheckedLocking:WARN",
"-Xep:ElementsCountedInLoop:WARN",
"-Xep:EqualsHashCode:WARN",
"-Xep:EqualsIncompatibleType:WARN",
"-Xep:ExpectedExceptionChecker:ERROR",
"-Xep:Finally:WARN",
"-Xep:FloatingPointLiteralPrecision:WARN",
"-Xep:FragmentInjection:WARN",
"-Xep:FragmentNotInstantiable:WARN",
"-Xep:FunctionalInterfaceClash:WARN",
"-Xep:FutureReturnValueIgnored:WARN",
"-Xep:GetClassOnEnum:WARN",
"-Xep:ImmutableAnnotationChecker:WARN",
"-Xep:ImmutableEnumChecker:WARN",
"-Xep:IncompatibleModifiers:WARN",
"-Xep:InjectOnConstructorOfAbstractClass:WARN",
"-Xep:InputStreamSlowMultibyteRead:WARN",
"-Xep:IterableAndIterator:WARN",
"-Xep:JUnit3FloatingPointComparisonWithoutDelta:WARN",
"-Xep:JUnitAmbiguousTestClass:WARN",
"-Xep:LiteralClassName:WARN",
"-Xep:MissingFail:WARN",
"-Xep:MissingOverride:WARN",
"-Xep:MutableConstantField:WARN",
"-Xep:NarrowingCompoundAssignment:WARN",
"-Xep:NonAtomicVolatileUpdate:WARN",
"-Xep:NonOverridingEquals:WARN",
"-Xep:NullableConstructor:WARN",
"-Xep:NullablePrimitive:WARN",
"-Xep:NullableVoid:WARN",
"-Xep:OperatorPrecedence:WARN",
"-Xep:OverridesGuiceInjectableMethod:WARN",
"-Xep:PreconditionsInvalidPlaceholder:WARN",
"-Xep:ProtoFieldPreconditionsCheckNotNull:WARN",
"-Xep:ProtocolBufferOrdinal:WARN",
"-Xep:RequiredModifiers:WARN",
"-Xep:ShortCircuitBoolean:WARN",
"-Xep:SimpleDateFormatConstant:WARN",
"-Xep:StaticGuardedByInstance:WARN",
"-Xep:SynchronizeOnNonFinalField:WARN",
"-Xep:TruthConstantAsserts:WARN",
"-Xep:TypeParameterShadowing:WARN",
"-Xep:TypeParameterUnusedInFormals:WARN",
"-Xep:URLEqualsHashCode:WARN",
"-Xep:UnsynchronizedOverridesSynchronized:WARN",
"-Xep:WaitNotInLoop:WARN",
],
packages = ["error_prone_packages"],
)
package_group(
name = "error_prone_packages",
packages = [
"//gerrit-acceptance-framework/...",
"//gerrit-acceptance-tests/...",
"//gerrit-cache-h2/...",
"//gerrit-cache-mem/...",
"//gerrit-common/...",
"//gerrit-elasticsearch/...",
"//gerrit-extension-api/...",
"//gerrit-gpg/...",
"//gerrit-httpd/...",
"//gerrit-launcher/...",
"//gerrit-lucene/...",
"//gerrit-main/...",
"//gerrit-oauth/...",
"//gerrit-openid/...",
"//gerrit-patch-commonsnet/...",
"//gerrit-patch-jgit/...",
"//gerrit-pgm/...",
"//gerrit-plugin-api/...",
"//gerrit-plugin-gwtui/...",
"//gerrit-prettify/...",
"//gerrit-reviewdb/...",
"//gerrit-server/...",
"//gerrit-sshd/...",
"//gerrit-test-util/...",
"//gerrit-util-cli/...",
"//gerrit-util-http/...",
"//gerrit-util-ssl/...",
"//gerrit-war/...",
],
)