Make administrator, create-project a global capability
This gets rid of the special entries in system_config and gerrit.config related to who the Administrators group is, or which groups are permitted to create new projects on this server. An interesting side effect of this change is admins can now actually remove the blessed Administrators group and run the server entirely without it. Fine grained rules can be used for most permissions, and direct access to the All-Projects.git repository can be used for cases where the "Administrate Site" override power is needed. Another benefit is the 'Create Project' capability is now dynamic, and can be modified at runtime without a server restart. Bug: issue 742 Change-Id: I44702010a4a521fd67d986d5b20411002c9481dd
This commit is contained in:
@@ -29,6 +29,8 @@ import com.google.gerrit.reviewdb.SystemConfig;
|
||||
import com.google.gerrit.rules.PrologEnvironment;
|
||||
import com.google.gerrit.server.AccessPath;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.account.CapabilityControl;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
@@ -36,6 +38,7 @@ import com.google.gerrit.server.git.ProjectConfig;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.assistedinject.FactoryProvider;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@@ -194,6 +197,10 @@ public class RefControlTest extends TestCase {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
private final Map<Project.NameKey, ProjectState> all;
|
||||
private final AllProjectsName allProjectsName = new AllProjectsName("parent");
|
||||
private final ProjectCache projectCache;
|
||||
|
||||
private ProjectConfig local;
|
||||
private ProjectConfig parent;
|
||||
private final AccountGroup.UUID admin = new AccountGroup.UUID("test.admin");
|
||||
@@ -205,10 +212,10 @@ public class RefControlTest extends TestCase {
|
||||
|
||||
private final SystemConfig systemConfig;
|
||||
private final AuthConfig authConfig;
|
||||
private final CapabilityControl.Factory capabilityControlFactory;
|
||||
|
||||
public RefControlTest() {
|
||||
systemConfig = SystemConfig.create();
|
||||
systemConfig.adminGroupUUID = admin;
|
||||
systemConfig.batchUsersGroupUUID = anonymous;
|
||||
try {
|
||||
byte[] bin = "abcdefghijklmnopqrstuvwxyz".getBytes("UTF-8");
|
||||
@@ -217,6 +224,37 @@ public class RefControlTest extends TestCase {
|
||||
throw new RuntimeException("Cannot encode key", err);
|
||||
}
|
||||
|
||||
all = new HashMap<Project.NameKey, ProjectState>();
|
||||
projectCache = new ProjectCache() {
|
||||
@Override
|
||||
public ProjectState getAllProjects() {
|
||||
return get(allProjectsName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectState get(Project.NameKey projectName) {
|
||||
return all.get(projectName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Project p) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Project.NameKey> all() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Project.NameKey> byName(String prefix) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateProject(Project.NameKey newProjectName) {
|
||||
}
|
||||
};
|
||||
|
||||
Injector injector = Guice.createInjector(new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
@@ -224,11 +262,18 @@ public class RefControlTest extends TestCase {
|
||||
.annotatedWith(GerritServerConfig.class) //
|
||||
.toInstance(new Config());
|
||||
|
||||
bind(CapabilityControl.Factory.class)
|
||||
.toProvider(FactoryProvider.newFactory(
|
||||
CapabilityControl.Factory.class,
|
||||
CapabilityControl.class));
|
||||
|
||||
bind(ProjectCache.class).toInstance(projectCache);
|
||||
bind(SystemConfig.class).toInstance(systemConfig);
|
||||
bind(AuthConfig.class);
|
||||
}
|
||||
});
|
||||
authConfig = injector.getInstance(AuthConfig.class);
|
||||
capabilityControlFactory = injector.getInstance(CapabilityControl.Factory.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -287,42 +332,14 @@ public class RefControlTest extends TestCase {
|
||||
}
|
||||
|
||||
private ProjectState newProjectState() {
|
||||
final Map<Project.NameKey, ProjectState> all =
|
||||
new HashMap<Project.NameKey, ProjectState>();
|
||||
final ProjectCache projectCache = new ProjectCache() {
|
||||
@Override
|
||||
public ProjectState get(Project.NameKey projectName) {
|
||||
return all.get(projectName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Project p) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Project.NameKey> all() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Project.NameKey> byName(String prefix) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateProject(Project.NameKey newProjectName) {
|
||||
}
|
||||
};
|
||||
|
||||
PrologEnvironment.Factory envFactory = null;
|
||||
GitRepositoryManager mgr = null;
|
||||
Project.NameKey wildProject = new Project.NameKey("All-Projects");
|
||||
ProjectControl.AssistedFactory projectControlFactory = null;
|
||||
all.put(local.getProject().getNameKey(), new ProjectState(
|
||||
projectCache, wildProject, projectControlFactory,
|
||||
projectCache, allProjectsName, projectControlFactory,
|
||||
envFactory, mgr, local));
|
||||
all.put(parent.getProject().getNameKey(), new ProjectState(
|
||||
projectCache, wildProject, projectControlFactory,
|
||||
projectCache, allProjectsName, projectControlFactory,
|
||||
envFactory, mgr, parent));
|
||||
return all.get(local.getProject().getNameKey());
|
||||
}
|
||||
@@ -331,7 +348,9 @@ public class RefControlTest extends TestCase {
|
||||
private final Set<AccountGroup.UUID> groups;
|
||||
|
||||
MockUser(AccountGroup.UUID[] groupId) {
|
||||
super(null, AccessPath.UNKNOWN, RefControlTest.this.authConfig);
|
||||
super(RefControlTest.this.capabilityControlFactory,
|
||||
AccessPath.UNKNOWN,
|
||||
RefControlTest.this.authConfig);
|
||||
groups = new HashSet<AccountGroup.UUID>(Arrays.asList(groupId));
|
||||
groups.add(registered);
|
||||
groups.add(anonymous);
|
||||
@@ -351,10 +370,5 @@ public class RefControlTest extends TestCase {
|
||||
public Collection<AccountProjectWatch> getNotificationFilters() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdministrator() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package com.google.gerrit.server.schema;
|
||||
|
||||
import com.google.gerrit.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.ApprovalCategory;
|
||||
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
|
||||
import com.google.gerrit.reviewdb.ReviewDb;
|
||||
@@ -71,9 +70,6 @@ public class SchemaCreatorTest extends TestCase {
|
||||
db.assertSchemaVersion();
|
||||
final SystemConfig config = db.getSystemConfig();
|
||||
assertNotNull(config);
|
||||
assertNotNull(config.adminGroupId);
|
||||
assertNotNull(config.anonymousGroupId);
|
||||
assertNotNull(config.registeredGroupId);
|
||||
|
||||
// By default sitePath is set to the current working directory.
|
||||
//
|
||||
@@ -95,58 +91,10 @@ public class SchemaCreatorTest extends TestCase {
|
||||
final SystemConfig act = db.getSystemConfig();
|
||||
|
||||
assertNotSame(exp, act);
|
||||
assertEquals(exp.adminGroupId, act.adminGroupId);
|
||||
assertEquals(exp.anonymousGroupId, act.anonymousGroupId);
|
||||
assertEquals(exp.registeredGroupId, act.registeredGroupId);
|
||||
assertEquals(exp.sitePath, act.sitePath);
|
||||
assertEquals(exp.registerEmailPrivateKey, act.registerEmailPrivateKey);
|
||||
}
|
||||
|
||||
public void testCreateSchema_Group_Administrators() throws OrmException {
|
||||
db.create();
|
||||
final SystemConfig config = db.getSystemConfig();
|
||||
final ReviewDb c = db.open();
|
||||
try {
|
||||
final AccountGroup admin = c.accountGroups().get(config.adminGroupId);
|
||||
assertNotNull(admin);
|
||||
assertEquals(config.adminGroupId, admin.getId());
|
||||
assertEquals("Administrators", admin.getName());
|
||||
assertSame(AccountGroup.Type.INTERNAL, admin.getType());
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateSchema_Group_AnonymousUsers() throws OrmException {
|
||||
db.create();
|
||||
final SystemConfig config = db.getSystemConfig();
|
||||
final ReviewDb c = db.open();
|
||||
try {
|
||||
final AccountGroup anon = c.accountGroups().get(config.anonymousGroupId);
|
||||
assertNotNull(anon);
|
||||
assertEquals(config.anonymousGroupId, anon.getId());
|
||||
assertEquals("Anonymous Users", anon.getName());
|
||||
assertSame(AccountGroup.Type.SYSTEM, anon.getType());
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateSchema_Group_RegisteredUsers() throws OrmException {
|
||||
db.create();
|
||||
final SystemConfig config = db.getSystemConfig();
|
||||
final ReviewDb c = db.open();
|
||||
try {
|
||||
final AccountGroup reg = c.accountGroups().get(config.registeredGroupId);
|
||||
assertNotNull(reg);
|
||||
assertEquals(config.registeredGroupId, reg.getId());
|
||||
assertEquals("Registered Users", reg.getName());
|
||||
assertSame(AccountGroup.Type.SYSTEM, reg.getType());
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateSchema_ApprovalCategory_CodeReview()
|
||||
throws OrmException {
|
||||
final ReviewDb c = db.create().open();
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.reviewdb.SystemConfig;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.GerritPersonIdentProvider;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
@@ -80,6 +81,9 @@ public class SchemaUpdaterTest extends TestCase {
|
||||
.annotatedWith(GerritPersonIdent.class) //
|
||||
.toProvider(GerritPersonIdentProvider.class);
|
||||
|
||||
bind(AllProjectsName.class)
|
||||
.toInstance(new AllProjectsName("All-Projects"));
|
||||
|
||||
bind(GitRepositoryManager.class) //
|
||||
.to(LocalDiskRepositoryManager.class);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.reviewdb.SystemConfig;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.GerritPersonIdentProvider;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.config.SitePath;
|
||||
import com.google.gerrit.server.config.SystemConfigProvider;
|
||||
@@ -144,7 +145,11 @@ public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
|
||||
final ReviewDb c = open();
|
||||
try {
|
||||
try {
|
||||
new SchemaCreator(new File("."), schemaVersion, null,
|
||||
new SchemaCreator(
|
||||
new File("."),
|
||||
schemaVersion,
|
||||
null,
|
||||
new AllProjectsName("Test-Projects"),
|
||||
new PersonIdent("name", "email@site")).create(c);
|
||||
} catch (IOException e) {
|
||||
throw new OrmException("Cannot create in-memory database", e);
|
||||
|
||||
Reference in New Issue
Block a user