Merge changes from topic 'make-names-of-system-groups-configurable'

* changes:
  Make names of system groups configurable
  Refactor: Make static methods in SystemGroupBackend non-static
  Add support for performing checks on Gerrit start up
This commit is contained in:
ekempin
2017-02-01 07:13:40 +00:00
committed by Gerrit Code Review
30 changed files with 401 additions and 65 deletions

View File

@@ -2201,6 +2201,29 @@ all registered users.
+
By default, false.
[[groups.uuid.name]]groups.<uuid>.name::
+
Display name for group with the given UUID.
+
This option is only supported for system groups (scheme 'global').
+
E.g. this parameter can be used to configure another name for the
`Anonymous Users` group:
+
----
[groups "global:Anonymous-Users"]
name = All Users
----
+
When setting this parameter it should be verified that there is no
existing group with the same name (case-insensitive). Configuring an
ambiguous name makes Gerrit fail on startup. Once set Gerrit ensures
that it is not possible to create a group with this name. Gerrit also
keeps the default name reserved so that it cannot be used for new
groups either. This means there is no danger of ambiguous group names
when this parameter is removed and the system group uses the default
name again.
[[http]]
=== Section http

View File

@@ -84,6 +84,7 @@ import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexer;
@@ -246,6 +247,9 @@ public abstract class AbstractDaemonTest {
@Inject
protected ChangeResource.Factory changeResourceFactory;
@Inject
protected SystemGroupBackend systemGroupBackend;
@Inject
private EventRecorder.Factory eventRecorderFactory;

View File

@@ -98,7 +98,6 @@ import com.google.gerrit.server.config.AnonymousCowardNameProvider;
import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.ChangeMessageModifier;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.Util;
@@ -1231,7 +1230,7 @@ public class ChangeIT extends AbstractDaemonTest {
cfg.getLabelSections().put(verified.getName(), verified);
AccountGroup.UUID registeredUsers =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
String heads = RefNames.REFS_HEADS + "*";
Util.allow(cfg, Permission.forLabel(Util.verified().getName()), -1, 1,
registeredUsers, heads);
@@ -1526,9 +1525,9 @@ public class ChangeIT extends AbstractDaemonTest {
cfg.getLabelSections().put(verified.getName(), verified);
String heads = "refs/heads/*";
AccountGroup.UUID owners =
SystemGroupBackend.getGroup(CHANGE_OWNER).getUUID();
systemGroupBackend.getGroup(CHANGE_OWNER).getUUID();
AccountGroup.UUID registered =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
Util.allow(cfg,
Permission.forLabel(verified.getName()), -1, 1, owners, heads);
Util.allow(cfg,
@@ -1825,7 +1824,7 @@ public class ChangeIT extends AbstractDaemonTest {
cfg.getLabelSections().put(custom2.getName(), custom2);
String heads = "refs/heads/*";
AccountGroup.UUID anon =
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
Util.allow(cfg, Permission.forLabel("Verified"), -1, 1, anon, heads);
Util.allow(cfg, Permission.forLabel("Custom1"), -1, 1, anon, heads);
Util.allow(cfg, Permission.forLabel("Custom2"), -1, 1, anon, heads);
@@ -2391,7 +2390,7 @@ public class ChangeIT extends AbstractDaemonTest {
LabelType verified = Util.verified();
cfg.getLabelSections().put(verified.getName(), verified);
AccountGroup.UUID registeredUsers =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
String heads = RefNames.REFS_HEADS + "*";
Util.allow(cfg, Permission.forLabel(verified.getName()), -1, 1,
registeredUsers, heads);
@@ -2453,7 +2452,7 @@ public class ChangeIT extends AbstractDaemonTest {
LabelType verified = Util.verified();
cfg.getLabelSections().put(verified.getName(), verified);
AccountGroup.UUID registeredUsers =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
String heads = RefNames.REFS_HEADS + "*";
Util.allow(cfg, Permission.forLabel(verified.getName()), -1, 1,
registeredUsers, heads);
@@ -2548,7 +2547,7 @@ public class ChangeIT extends AbstractDaemonTest {
// Allow user to approve
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
AccountGroup.UUID registeredUsers =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
String heads = RefNames.REFS_HEADS + "*";
Util.allow(cfg, Permission.forLabel(Util.codeReview().getName()), -2, 2,
registeredUsers, heads);

View File

@@ -45,7 +45,6 @@ import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.Util;
import org.eclipse.jgit.junit.TestRepository;
@@ -82,7 +81,7 @@ public class StickyApprovalsIT extends AbstractDaemonTest {
cfg.getLabelSections().put(verified.getName(), verified);
AccountGroup.UUID registeredUsers =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
String heads = RefNames.REFS_HEADS + "*";
Util.allow(cfg, Permission.forLabel(Util.codeReview().getName()), -2, 2,
registeredUsers, heads);

View File

@@ -17,12 +17,15 @@ package com.google.gerrit.acceptance.api.group;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.api.group.GroupAssert.assertGroupInfo;
import static com.google.gerrit.acceptance.rest.account.AccountAssert.assertAccountInfos;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static java.util.stream.Collectors.toList;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.extensions.api.groups.GroupApi;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.common.AccountInfo;
@@ -176,6 +179,24 @@ public class GroupsIT extends AbstractDaemonTest {
gApi.groups().create(newGroupName);
}
@Test
@GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
public void createGroupWithConfiguredNameOfSystemGroup_Conflict()
throws Exception {
exception.expect(ResourceConflictException.class);
exception.expectMessage("group 'All Users' already exists");
gApi.groups().create("all users");
}
@Test
@GerritConfig(name = "groups.global:Anonymous-Users.name", value = "All Users")
public void createGroupWithDefaultNameOfSystemGroup_Conflict()
throws Exception {
exception.expect(ResourceConflictException.class);
exception.expectMessage("group name 'Anonymous Users' is reserved");
gApi.groups().create("anonymous users");
}
@Test
public void createGroupWithProperties() throws Exception {
GroupInput in = new GroupInput();
@@ -210,6 +231,41 @@ public class GroupsIT extends AbstractDaemonTest {
assertGroupInfo(expectedGroup, group);
}
@Test
@GerritConfig(name = "groups.global:Anonymous-Users.name",
value = "All Users")
public void getSystemGroupByConfiguredName() throws Exception {
GroupReference anonymousUsersGroup =
systemGroupBackend.getGroup(ANONYMOUS_USERS);
assertThat(anonymousUsersGroup.getName()).isEqualTo("All Users");
GroupInfo group =
gApi.groups().id(anonymousUsersGroup.getUUID().get()).get();
assertThat(group.name).isEqualTo(anonymousUsersGroup.getName());
group = gApi.groups().id(anonymousUsersGroup.getName()).get();
assertThat(group.id)
.isEqualTo(Url.encode((anonymousUsersGroup.getUUID().get())));
}
@Test
public void getSystemGroupByDefaultName() throws Exception {
GroupReference anonymousUsersGroup =
systemGroupBackend.getGroup(ANONYMOUS_USERS);
GroupInfo group = gApi.groups().id("Anonymous Users").get();
assertThat(group.name).isEqualTo(anonymousUsersGroup.getName());
assertThat(group.id)
.isEqualTo(Url.encode((anonymousUsersGroup.getUUID().get())));
}
@Test
@GerritConfig(name = "groups.global:Anonymous-Users.name",
value = "All Users")
public void getSystemGroupByDefaultName_NotFound() throws Exception {
exception.expect(ResourceNotFoundException.class);
gApi.groups().id("Anonymous-Users").get();
}
@Test
public void groupName() throws Exception {
String name = name("group");

View File

@@ -53,7 +53,6 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.project.Util;
import com.google.gerrit.server.query.change.ChangeData;
@@ -106,7 +105,7 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
patchSetLock = Util.patchSetLock();
cfg.getLabelSections().put(patchSetLock.getName(), patchSetLock);
AccountGroup.UUID anonymousUsers =
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
Util.allow(cfg, Permission.forLabel(patchSetLock.getName()), 0, 1, anonymousUsers,
"refs/heads/*");
saveProjectConfig(cfg);
@@ -534,7 +533,7 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
value(-1, "Negative"));
ProjectConfig config = projectCache.checkedGet(project).getConfig();
AccountGroup.UUID anon =
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
String heads = "refs/heads/*";
Util.allow(config, Permission.forLabel("Custom-Label"), -1, 1, anon, heads);
config.getLabelSections().put(Q.getName(), Q);

View File

@@ -59,7 +59,6 @@ import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.account.AccountControl;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.inject.Inject;
@@ -611,7 +610,7 @@ public class ImpersonationIT extends AbstractDaemonTest {
String forCodeReviewAs = Permission.forLabelAs(codeReviewType.getName());
String heads = "refs/heads/*";
AccountGroup.UUID uuid =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
Util.allow(cfg, forCodeReviewAs, -1, 1, uuid, heads);
saveProjectConfig(project, cfg);
}
@@ -620,7 +619,7 @@ public class ImpersonationIT extends AbstractDaemonTest {
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
String heads = "refs/heads/*";
AccountGroup.UUID uuid =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
Util.allow(cfg, Permission.SUBMIT_AS, uuid, heads);
Util.allow(cfg, Permission.SUBMIT, uuid, heads);
LabelType codeReviewType = Util.codeReview();
@@ -639,14 +638,14 @@ public class ImpersonationIT extends AbstractDaemonTest {
private void allowRunAs() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(allProjects).getConfig();
Util.allow(cfg, GlobalCapability.RUN_AS,
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID());
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID());
saveProjectConfig(allProjects, cfg);
}
private void removeRunAs() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(allProjects).getConfig();
Util.remove(cfg, GlobalCapability.RUN_AS,
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID());
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID());
saveProjectConfig(allProjects, cfg);
}

View File

@@ -84,7 +84,7 @@ public class ChangeOwnerIT extends AbstractDaemonTest {
AccessSection s = config.getAccessSection("refs/heads/*", true);
Permission p = s.getPermission(LABEL + "Code-Review", true);
PermissionRule rule = new PermissionRule(config
.resolve(SystemGroupBackend.getGroup(SystemGroupBackend.CHANGE_OWNER)));
.resolve(systemGroupBackend.getGroup(SystemGroupBackend.CHANGE_OWNER)));
rule.setMin(-2);
rule.setMax(+2);
p.add(rule);

View File

@@ -33,7 +33,6 @@ import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.Util;
import org.eclipse.jgit.junit.TestRepository;
@@ -166,7 +165,7 @@ public class MoveChangeIT extends AbstractDaemonTest {
new Branch.NameKey(r.getChange().change().getProject(), "blocked_branch");
createBranch(newBranch);
block(Permission.PUSH,
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID(),
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID(),
"refs/for/" + newBranch.get());
exception.expect(AuthException.class);
exception.expectMessage("Move not permitted");
@@ -181,7 +180,7 @@ public class MoveChangeIT extends AbstractDaemonTest {
new Branch.NameKey(r.getChange().change().getProject(), "moveTest");
createBranch(newBranch);
block(Permission.ABANDON,
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID(),
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID(),
r.getChange().change().getDest().get());
setApiUser(user);
exception.expect(AuthException.class);
@@ -228,7 +227,7 @@ public class MoveChangeIT extends AbstractDaemonTest {
LabelType patchSetLock = Util.patchSetLock();
cfg.getLabelSections().put(patchSetLock.getName(), patchSetLock);
AccountGroup.UUID registeredUsers =
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID();
Util.allow(cfg, Permission.forLabel(patchSetLock.getName()), 0, 1, registeredUsers,
"refs/heads/*");
saveProjectConfig(cfg);

View File

@@ -33,7 +33,6 @@ import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.Util;
import com.google.inject.Inject;
@@ -63,7 +62,7 @@ public class CommentAddedEventIT extends AbstractDaemonTest {
public void setUp() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
AccountGroup.UUID anonymousUsers =
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
Util.allow(cfg, Permission.forLabel(label.getName()), -1, 1, anonymousUsers,
"refs/heads/*");
Util.allow(cfg, Permission.forLabel(pLabel.getName()), 0, 1, anonymousUsers,

View File

@@ -68,7 +68,6 @@ import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.RepoRefCache;
import com.google.gerrit.server.git.UpdateException;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.ChangeBundle;
import com.google.gerrit.server.notedb.ChangeBundleReader;
import com.google.gerrit.server.notedb.ChangeNotes;
@@ -1349,14 +1348,14 @@ public class ChangeRebuilderIT extends AbstractDaemonTest {
private void allowRunAs() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(allProjects).getConfig();
Util.allow(cfg, GlobalCapability.RUN_AS,
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
saveProjectConfig(allProjects, cfg);
}
private void removeRunAs() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(allProjects).getConfig();
Util.remove(cfg, GlobalCapability.RUN_AS,
SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
systemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
saveProjectConfig(allProjects, cfg);
}

View File

@@ -35,7 +35,6 @@ import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.Util;
import com.google.inject.Inject;
@@ -65,7 +64,7 @@ public class CustomLabelIT extends AbstractDaemonTest {
public void setUp() throws Exception {
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
AccountGroup.UUID anonymousUsers =
SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
systemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
Util.allow(cfg, Permission.forLabel(label.getName()), -1, 1, anonymousUsers,
"refs/heads/*");
Util.allow(cfg, Permission.forLabel(P.getName()), 0, 1, anonymousUsers,

View File

@@ -47,6 +47,7 @@ import com.google.gerrit.pgm.util.ErrorLogFile;
import com.google.gerrit.pgm.util.LogFileCompressor;
import com.google.gerrit.pgm.util.RuntimeShutdown;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.server.StartupChecks;
import com.google.gerrit.server.account.InternalAccountDirectory;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.change.ChangeCleanupRunner;
@@ -379,6 +380,7 @@ public class Daemon extends SiteProgram {
modules.add(new PluginRestApiModule());
modules.add(new RestCacheAdminModule());
modules.add(new GpgModule(config));
modules.add(new StartupChecks.Module());
if (MoreObjects.firstNonNull(httpd, true)) {
modules.add(new CanonicalWebUrlModule() {
@Override

View File

@@ -0,0 +1,33 @@
// 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.google.gerrit.server;
import com.google.gerrit.extensions.events.LifecycleListener;
/**
* Check executed on Gerrit startup.
*/
public interface StartupCheck {
/**
* Performs Gerrit startup check, can abort startup by throwing
* {@link StartupException}.
* <p>
* Called on Gerrit startup after all {@link LifecycleListener} have been
* invoked.
*
* @throws StartupException thrown if Gerrit startup should be aborted
*/
void check() throws StartupException;
}

View File

@@ -0,0 +1,56 @@
// 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.google.gerrit.server;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.account.UniversalGroupBackend;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class StartupChecks implements LifecycleListener {
public static class Module extends LifecycleModule {
@Override
protected void configure() {
DynamicSet.setOf(binder(), StartupCheck.class);
listener().to(StartupChecks.class);
DynamicSet.bind(binder(), StartupCheck.class)
.to(UniversalGroupBackend.ConfigCheck.class);
DynamicSet.bind(binder(), StartupCheck.class)
.to(SystemGroupBackend.NameCheck.class);
}
}
private final DynamicSet<StartupCheck> startupChecks;
@Inject
StartupChecks(DynamicSet<StartupCheck> startupChecks) {
this.startupChecks = startupChecks;
}
@Override
public void start() throws StartupException {
for (StartupCheck startupCheck : startupChecks) {
startupCheck.check();
}
}
@Override
public void stop() {
}
}

View File

@@ -0,0 +1,27 @@
// 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.google.gerrit.server;
public class StartupException extends RuntimeException {
private static final long serialVersionUID = 1L;
public StartupException(String message) {
super(message);
}
public StartupException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -42,6 +42,7 @@ public class CapabilityCollection {
CapabilityCollection create(@Nullable AccessSection section);
}
private final SystemGroupBackend systemGroupBackend;
private final ImmutableMap<String, ImmutableList<PermissionRule>> permissions;
public final ImmutableList<PermissionRule> administrateServer;
@@ -52,8 +53,11 @@ public class CapabilityCollection {
@Inject
CapabilityCollection(
SystemGroupBackend systemGroupBackend,
@AdministrateServerGroups ImmutableSet<GroupReference> admins,
@Assisted @Nullable AccessSection section) {
this.systemGroupBackend = systemGroupBackend;
if (section == null) {
section = new AccessSection(AccessSection.GLOBAL_CAPABILITIES);
}
@@ -119,12 +123,10 @@ public class CapabilityCollection {
return r != null ? r : ImmutableList.<PermissionRule> of();
}
private static final GroupReference anonymous = SystemGroupBackend
.getGroup(SystemGroupBackend.ANONYMOUS_USERS);
private static void configureDefaults(Map<String, List<PermissionRule>> out,
private void configureDefaults(Map<String, List<PermissionRule>> out,
AccessSection section) {
configureDefault(out, section, GlobalCapability.QUERY_LIMIT, anonymous);
configureDefault(out, section, GlobalCapability.QUERY_LIMIT,
systemGroupBackend.getGroup(SystemGroupBackend.ANONYMOUS_USERS));
}
private static void configureDefault(Map<String, List<PermissionRule>> out,

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.account;
import static com.google.gerrit.server.account.GroupBackends.GROUP_REF_NAME_COMPARATOR;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
@@ -27,10 +28,14 @@ import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.StartupCheck;
import com.google.gerrit.server.StartupException;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.project.ProjectControl;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -208,4 +213,38 @@ public class UniversalGroupBackend implements GroupBackend {
}
return false;
}
public static class ConfigCheck implements StartupCheck {
private final Config cfg;
private final UniversalGroupBackend universalGroupBackend;
@Inject
ConfigCheck(@GerritServerConfig Config cfg,
UniversalGroupBackend groupBackend) {
this.cfg = cfg;
this.universalGroupBackend = groupBackend;
}
@Override
public void check() throws StartupException {
String invalid = cfg.getSubsections("groups").stream()
.filter(
sub -> {
AccountGroup.UUID uuid = new AccountGroup.UUID(sub);
GroupBackend groupBackend = universalGroupBackend.backend(uuid);
return groupBackend == null || groupBackend.get(uuid) == null;
})
.map(u -> "'" + u + "'")
.collect(joining(","));
if (!invalid.isEmpty()) {
throw new StartupException(String.format(
"Subsections for 'groups' in gerrit.config must be valid group"
+ " UUIDs. The following group UUIDs could not be resolved: "
+ invalid
+ " Please remove/fix these 'groups' subsections in"
+ " gerrit.config."));
}
}
}
}

View File

@@ -73,6 +73,7 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
private final GroupJson json;
private final DynamicSet<GroupCreationValidationListener> groupCreationValidationListeners;
private final AddMembers addMembers;
private final SystemGroupBackend systemGroupBackend;
private final boolean defaultVisibleToAll;
private final String name;
@@ -86,6 +87,7 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
GroupJson json,
DynamicSet<GroupCreationValidationListener> groupCreationValidationListeners,
AddMembers addMembers,
SystemGroupBackend systemGroupBackend,
@GerritServerConfig Config cfg,
@Assisted String name) {
this.self = self;
@@ -96,6 +98,7 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
this.json = json;
this.groupCreationValidationListeners = groupCreationValidationListeners;
this.addMembers = addMembers;
this.systemGroupBackend = systemGroupBackend;
this.defaultVisibleToAll = cfg.getBoolean("groups", "newGroupsVisibleToAll", false);
this.name = name;
}
@@ -169,7 +172,7 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
throws OrmException, ResourceConflictException, IOException {
// Do not allow creating groups with the same name as system groups
for (String name : SystemGroupBackend.getNames()) {
for (String name : systemGroupBackend.getNames()) {
if (name.toLowerCase(Locale.US).equals(
createGroupArgs.getGroupName().toLowerCase(Locale.US))) {
throw new ResourceConflictException("group '" + name
@@ -177,6 +180,14 @@ public class CreateGroup implements RestModifyView<TopLevelResource, GroupInput>
}
}
for (String name : systemGroupBackend.getReservedNames()) {
if (name.toLowerCase(Locale.US).equals(
createGroupArgs.getGroupName().toLowerCase(Locale.US))) {
throw new ResourceConflictException("group name '" + name
+ "' is reserved");
}
}
AccountGroup.Id groupId = new AccountGroup.Id(db.nextAccountGroupId());
AccountGroup.UUID uuid =
GroupUUID.make(

View File

@@ -17,20 +17,31 @@ package com.google.gerrit.server.group;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.stream.Collectors.toSet;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.StartupCheck;
import com.google.gerrit.server.StartupException;
import com.google.gerrit.server.account.AbstractGroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.project.ProjectControl;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.Config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -38,6 +49,7 @@ import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@Singleton
public class SystemGroupBackend extends AbstractGroupBackend {
public static final String SYSTEM_GROUP_SCHEME = "global:";
@@ -57,8 +69,6 @@ public class SystemGroupBackend extends AbstractGroupBackend {
public static final AccountGroup.UUID CHANGE_OWNER =
new AccountGroup.UUID(SYSTEM_GROUP_SCHEME + "Change-Owner");
private static final SortedMap<String, GroupReference> names;
private static final ImmutableMap<AccountGroup.UUID, GroupReference> uuids;
private static final AccountGroup.UUID[] all = {
ANONYMOUS_USERS,
REGISTERED_USERS,
@@ -66,22 +76,6 @@ public class SystemGroupBackend extends AbstractGroupBackend {
CHANGE_OWNER,
};
static {
SortedMap<String, GroupReference> n = new TreeMap<>();
ImmutableMap.Builder<AccountGroup.UUID, GroupReference> u =
ImmutableMap.builder();
for (AccountGroup.UUID uuid : all) {
int c = uuid.get().indexOf(':');
String name = uuid.get().substring(c + 1).replace('-', ' ');
GroupReference ref = new GroupReference(uuid, name);
n.put(ref.getName().toLowerCase(Locale.US), ref);
u.put(ref.getUUID(), ref);
}
names = Collections.unmodifiableSortedMap(n);
uuids = u.build();
}
public static boolean isSystemGroup(AccountGroup.UUID uuid) {
return uuid.get().startsWith(SYSTEM_GROUP_SCHEME);
}
@@ -94,14 +88,45 @@ public class SystemGroupBackend extends AbstractGroupBackend {
return ANONYMOUS_USERS.equals(uuid) || REGISTERED_USERS.equals(uuid);
}
public static GroupReference getGroup(AccountGroup.UUID uuid) {
private final ImmutableSet<String> reservedNames;
private final SortedMap<String, GroupReference> names;
private final ImmutableMap<AccountGroup.UUID, GroupReference> uuids;
@Inject
@VisibleForTesting
public SystemGroupBackend(@GerritServerConfig Config cfg) {
SortedMap<String, GroupReference> n = new TreeMap<>();
ImmutableMap.Builder<AccountGroup.UUID, GroupReference> u =
ImmutableMap.builder();
ImmutableSet.Builder<String> reservedNamesBuilder = ImmutableSet.builder();
for (AccountGroup.UUID uuid : all) {
int c = uuid.get().indexOf(':');
String defaultName = uuid.get().substring(c + 1).replace('-', ' ');
reservedNamesBuilder.add(defaultName);
String configuredName = cfg.getString("groups", uuid.get(), "name");
GroupReference ref = new GroupReference(uuid,
MoreObjects.firstNonNull(configuredName, defaultName));
n.put(ref.getName().toLowerCase(Locale.US), ref);
u.put(ref.getUUID(), ref);
}
reservedNames = reservedNamesBuilder.build();
names = Collections.unmodifiableSortedMap(n);
uuids = u.build();
}
public GroupReference getGroup(AccountGroup.UUID uuid) {
return checkNotNull(uuids.get(uuid), "group %s not found", uuid.get());
}
public static Set<String> getNames() {
public Set<String> getNames() {
return names.values().stream().map(r -> r.getName()).collect(toSet());
}
public Set<String> getReservedNames() {
return reservedNames;
}
@Override
public boolean handles(AccountGroup.UUID uuid) {
return isSystemGroup(uuid);
@@ -161,4 +186,48 @@ public class SystemGroupBackend extends AbstractGroupBackend {
ANONYMOUS_USERS,
REGISTERED_USERS));
}
public static class NameCheck implements StartupCheck {
private final Config cfg;
private final GroupCache groupCache;
@Inject
NameCheck(@GerritServerConfig Config cfg,
GroupCache groupCache) {
this.cfg = cfg;
this.groupCache = groupCache;
}
@Override
public void check() throws StartupException {
Map<AccountGroup.UUID, String> configuredNames = new HashMap<>();
Map<String, AccountGroup.UUID> byLowerCaseConfiguredName =
new HashMap<>();
for (AccountGroup.UUID uuid : all) {
String configuredName = cfg.getString("groups", uuid.get(), "name");
if (configuredName != null) {
configuredNames.put(uuid, configuredName);
byLowerCaseConfiguredName.put(configuredName.toLowerCase(Locale.US),
uuid);
}
}
if (configuredNames.isEmpty()) {
return;
}
for (AccountGroup g : groupCache.all()) {
String name = g.getName().toLowerCase(Locale.US);
if (byLowerCaseConfiguredName.keySet().contains(name)) {
AccountGroup.UUID uuidSystemGroup =
byLowerCaseConfiguredName.get(name);
throw new StartupException(String.format(
"The configured name '%s' for system group '%s' is ambiguous"
+ " with the name '%s' of existing group '%s'."
+ " Please remove/change the value for groups.%s.name in"
+ " gerrit.config.",
configuredNames.get(uuidSystemGroup), uuidSystemGroup.get(),
g.getName(), g.getGroupUUID().get(), uuidSystemGroup.get()));
}
}
}
}
}

View File

@@ -70,14 +70,15 @@ public class AllProjectsCreator {
AllProjectsCreator(
GitRepositoryManager mgr,
AllProjectsName allProjectsName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
this.mgr = mgr;
this.allProjectsName = allProjectsName;
this.serverUser = serverUser;
this.anonymous = SystemGroupBackend.getGroup(ANONYMOUS_USERS);
this.registered = SystemGroupBackend.getGroup(REGISTERED_USERS);
this.owners = SystemGroupBackend.getGroup(PROJECT_OWNERS);
this.anonymous = systemGroupBackend.getGroup(ANONYMOUS_USERS);
this.registered = systemGroupBackend.getGroup(REGISTERED_USERS);
this.owners = systemGroupBackend.getGroup(PROJECT_OWNERS);
}
public AllProjectsCreator setAdministrators(GroupReference admin) {

View File

@@ -54,11 +54,12 @@ public class AllUsersCreator {
AllUsersCreator(
GitRepositoryManager mgr,
AllUsersName allUsersName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
this.mgr = mgr;
this.allUsersName = allUsersName;
this.serverUser = serverUser;
this.registered = SystemGroupBackend.getGroup(REGISTERED_USERS);
this.registered = systemGroupBackend.getGroup(REGISTERED_USERS);
}
public AllUsersCreator setAdministrators(GroupReference admin) {

View File

@@ -25,6 +25,7 @@ import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
@@ -82,6 +83,7 @@ public class SchemaUpdater {
AllUsersName.class,
GitRepositoryManager.class,
SitePaths.class,
SystemGroupBackend.class,
}) {
rebind(parent, Key.get(c));
}

View File

@@ -58,6 +58,7 @@ public class Schema_125 extends SchemaVersion {
private final GitRepositoryManager repoManager;
private final AllUsersName allUsersName;
private final AllProjectsName allProjectsName;
private final SystemGroupBackend systemGroupBackend;
private final PersonIdent serverUser;
@Inject
@@ -65,11 +66,13 @@ public class Schema_125 extends SchemaVersion {
GitRepositoryManager repoManager,
AllUsersName allUsersName,
AllProjectsName allProjectsName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.repoManager = repoManager;
this.allUsersName = allUsersName;
this.allProjectsName = allProjectsName;
this.systemGroupBackend = systemGroupBackend;
this.serverUser = serverUser;
}
@@ -82,7 +85,7 @@ public class Schema_125 extends SchemaVersion {
config.getAccessSection(RefNames.REFS_USERS + "*", true)
.remove(new Permission(Permission.READ));
GroupReference registered = SystemGroupBackend.getGroup(REGISTERED_USERS);
GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
AccessSection users = config.getAccessSection(
RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}", true);
grant(config, users, Permission.READ, true, registered);

View File

@@ -46,16 +46,19 @@ public class Schema_126 extends SchemaVersion {
private final GitRepositoryManager repoManager;
private final AllUsersName allUsersName;
private final SystemGroupBackend systemGroupBackend;
private final PersonIdent serverUser;
@Inject
Schema_126(Provider<Schema_125> prior,
GitRepositoryManager repoManager,
AllUsersName allUsersName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.repoManager = repoManager;
this.allUsersName = allUsersName;
this.systemGroupBackend = systemGroupBackend;
this.serverUser = serverUser;
}
@@ -70,7 +73,7 @@ public class Schema_126 extends SchemaVersion {
RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}";
config.remove(config.getAccessSection(refsUsersShardedId));
GroupReference registered = SystemGroupBackend.getGroup(REGISTERED_USERS);
GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
AccessSection users = config.getAccessSection(refsUsersShardedId, true);
grant(config, users, Permission.READ, false, true, registered);
grant(config, users, Permission.PUSH, false, true, registered);

View File

@@ -44,16 +44,19 @@ public class Schema_128 extends SchemaVersion {
private final GitRepositoryManager repoManager;
private final AllProjectsName allProjectsName;
private final SystemGroupBackend systemGroupBackend;
private final PersonIdent serverUser;
@Inject
Schema_128(Provider<Schema_127> prior,
GitRepositoryManager repoManager,
AllProjectsName allProjectsName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.repoManager = repoManager;
this.allProjectsName = allProjectsName;
this.systemGroupBackend = systemGroupBackend;
this.serverUser = serverUser;
}
@@ -64,7 +67,7 @@ public class Schema_128 extends SchemaVersion {
allProjectsName, git)) {
ProjectConfig config = ProjectConfig.read(md);
GroupReference registered = SystemGroupBackend.getGroup(REGISTERED_USERS);
GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
AccessSection refsFor = config.getAccessSection("refs/for/*", true);
grant(config, refsFor, Permission.ADD_PATCH_SET,
false, false, registered);

View File

@@ -49,16 +49,19 @@ public class Schema_135 extends SchemaVersion {
private final GitRepositoryManager repoManager;
private final AllProjectsName allProjectsName;
private final SystemGroupBackend systemGroupBackend;
private final PersonIdent serverUser;
@Inject
Schema_135(Provider<Schema_134> prior,
GitRepositoryManager repoManager,
AllProjectsName allProjectsName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.repoManager = repoManager;
this.allProjectsName = allProjectsName;
this.systemGroupBackend = systemGroupBackend;
this.serverUser = serverUser;
}
@@ -81,7 +84,7 @@ public class Schema_135 extends SchemaVersion {
.getRules()
.stream()
.map(PermissionRule::getGroup),
Stream.of(SystemGroupBackend.getGroup(PROJECT_OWNERS)))
Stream.of(systemGroupBackend.getGroup(PROJECT_OWNERS)))
.filter(g -> createRefsMetaConfigPermission.getRule(g) == null)
.collect(toSet());

View File

@@ -38,6 +38,7 @@ import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.testutil.GerritBaseTests;
import org.easymock.IAnswer;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;
@@ -57,7 +58,7 @@ public class UniversalGroupBackendTest extends GerritBaseTests {
user = createNiceMock(IdentifiedUser.class);
replay(user);
backends = new DynamicSet<>();
backends.add(new SystemGroupBackend());
backends.add(new SystemGroupBackend(new Config()));
backend = new UniversalGroupBackend(backends);
}

View File

@@ -29,6 +29,7 @@ import com.google.gerrit.server.config.AnonymousCowardNameProvider;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.testutil.InMemoryDatabase;
import com.google.gerrit.testutil.InMemoryH2Type;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
@@ -109,6 +110,8 @@ public class SchemaUpdaterTest {
.toProvider(AnonymousCowardNameProvider.class);
bind(DataSourceType.class).to(InMemoryH2Type.class);
bind(SystemGroupBackend.class);
}
}).getInstance(SchemaUpdater.class);

View File

@@ -32,6 +32,7 @@ import com.google.gerrit.lucene.LuceneIndexModule;
import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
import com.google.gerrit.pgm.util.LogFileCompressor;
import com.google.gerrit.server.LibModuleLoader;
import com.google.gerrit.server.StartupChecks;
import com.google.gerrit.server.account.InternalAccountDirectory;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.change.ChangeCleanupRunner;
@@ -319,6 +320,7 @@ public class WebAppInitializer extends GuiceServletContextListener
modules.add(new PluginRestApiModule());
modules.add(new RestCacheAdminModule());
modules.add(new GpgModule(config));
modules.add(new StartupChecks.Module());
// Index module shutdown must happen before work queue shutdown, otherwise
// work queue can get stuck waiting on index futures that will never return.