Change the admin group to be blessed by system_config, not by name

This permits the admin group to be renamed, but also prevents a
rogue group from taking on the blessed personality.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2008-12-31 10:17:36 -08:00
parent c2b3d71207
commit 8f46ab6321
7 changed files with 41 additions and 55 deletions

View File

@@ -31,7 +31,6 @@ import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusListenerAdapter; import com.google.gwt.user.client.ui.FocusListenerAdapter;
import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SourcesTableEvents; import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TableListener; import com.google.gwt.user.client.ui.TableListener;
@@ -50,11 +49,9 @@ public class AccountGroupScreen extends AccountScreen {
private AccountInfoCache accounts = AccountInfoCache.empty(); private AccountInfoCache accounts = AccountInfoCache.empty();
private MemberTable members; private MemberTable members;
private Panel groupNamePanel;
private TextBox groupNameTxt; private TextBox groupNameTxt;
private Button saveName; private Button saveName;
private Panel ownerPanel;
private TextBox ownerTxtBox; private TextBox ownerTxtBox;
private SuggestBox ownerTxt; private SuggestBox ownerTxt;
private Button saveOwner; private Button saveOwner;
@@ -112,7 +109,7 @@ public class AccountGroupScreen extends AccountScreen {
} }
private void initName() { private void initName() {
groupNamePanel = new VerticalPanel(); final VerticalPanel groupNamePanel = new VerticalPanel();
groupNameTxt = new TextBox(); groupNameTxt = new TextBox();
groupNameTxt.setVisibleLength(60); groupNameTxt.setVisibleLength(60);
groupNamePanel.add(groupNameTxt); groupNamePanel.add(groupNameTxt);
@@ -137,7 +134,7 @@ public class AccountGroupScreen extends AccountScreen {
} }
private void initOwner() { private void initOwner() {
ownerPanel = new VerticalPanel(); final VerticalPanel ownerPanel = new VerticalPanel();
final Label ownerHdr = new Label(Util.C.headingOwner()); final Label ownerHdr = new Label(Util.C.headingOwner());
ownerHdr.setStyleName("gerrit-SmallHeading"); ownerHdr.setStyleName("gerrit-SmallHeading");
ownerPanel.add(ownerHdr); ownerPanel.add(ownerHdr);
@@ -251,17 +248,6 @@ public class AccountGroupScreen extends AccountScreen {
} }
private void display(final AccountGroupDetail result) { private void display(final AccountGroupDetail result) {
if (GroupAdminService.ADMIN_GROUP.equals(result.group.getNameKey())) {
ownerTxtBox.setEnabled(false);
ownerPanel.setVisible(false);
groupNameTxt.setEnabled(false);
groupNamePanel.setVisible(false);
} else {
ownerPanel.setVisible(true);
groupNamePanel.setVisible(true);
}
setTitleText(Util.M.group(result.group.getName())); setTitleText(Util.M.group(result.group.getName()));
groupNameTxt.setText(result.group.getName()); groupNameTxt.setText(result.group.getName());
ownerTxt.setText(result.ownerGroup.getName()); ownerTxt.setText(result.ownerGroup.getName());

View File

@@ -25,10 +25,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
public interface GroupAdminService extends RemoteJsonService { public interface GroupAdminService extends RemoteJsonService {
/** Special group, which must not be renamed as its "blessed". */
public static final AccountGroup.NameKey ADMIN_GROUP =
new AccountGroup.NameKey("admin");
@SignInRequired @SignInRequired
void ownedGroups(AsyncCallback<List<AccountGroup>> callback); void ownedGroups(AsyncCallback<List<AccountGroup>> callback);

View File

@@ -87,6 +87,10 @@ public final class SystemConfig {
@Column @Column
public int sshdPort; public int sshdPort;
/** Identity of the administration group; those with full access. */
@Column
public AccountGroup.Id adminGroupId;
protected SystemConfig() { protected SystemConfig() {
} }
} }

View File

@@ -14,7 +14,6 @@
package com.google.gerrit.server; package com.google.gerrit.server;
import com.google.gerrit.client.admin.GroupAdminService;
import com.google.gerrit.client.data.ApprovalType; import com.google.gerrit.client.data.ApprovalType;
import com.google.gerrit.client.data.GerritConfig; import com.google.gerrit.client.data.GerritConfig;
import com.google.gerrit.client.data.GitwebLink; import com.google.gerrit.client.data.GitwebLink;
@@ -150,16 +149,17 @@ public class GerritServer {
} }
private void initSystemConfig(final ReviewDb c) throws OrmException { private void initSystemConfig(final ReviewDb c) throws OrmException {
final AccountGroup admin =
new AccountGroup(new AccountGroup.NameKey("Administrators"),
new AccountGroup.Id(c.nextAccountGroupId()));
c.accountGroups().insert(Collections.singleton(admin));
final SystemConfig s = SystemConfig.create(); final SystemConfig s = SystemConfig.create();
s.xsrfPrivateKey = SignedToken.generateRandomKey(); s.xsrfPrivateKey = SignedToken.generateRandomKey();
s.accountPrivateKey = SignedToken.generateRandomKey(); s.accountPrivateKey = SignedToken.generateRandomKey();
s.sshdPort = 29418; s.sshdPort = 29418;
s.adminGroupId = admin.getId();
c.systemConfig().insert(Collections.singleton(s)); c.systemConfig().insert(Collections.singleton(s));
final AccountGroup admin =
new AccountGroup(GroupAdminService.ADMIN_GROUP, new AccountGroup.Id(c
.nextAccountGroupId()));
c.accountGroups().insert(Collections.singleton(admin));
} }
private void initVerifiedCategory(final ReviewDb c) throws OrmException { private void initVerifiedCategory(final ReviewDb c) throws OrmException {
@@ -303,4 +303,9 @@ public class GerritServer {
public RepositoryCache getRepositoryCache() { public RepositoryCache getRepositoryCache() {
return repositories; return repositories;
} }
/** Get the group whose members have full access to manage the site. */
public AccountGroup.Id getAdminGroupId() {
return sConfig.adminGroupId;
}
} }

View File

@@ -12,8 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package com.google.gerrit.client.admin; package com.google.gerrit.server;
import com.google.gerrit.client.admin.AccountGroupDetail;
import com.google.gerrit.client.admin.GroupAdminService;
import com.google.gerrit.client.data.AccountInfoCacheFactory; import com.google.gerrit.client.data.AccountInfoCacheFactory;
import com.google.gerrit.client.reviewdb.Account; import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountGroup; import com.google.gerrit.client.reviewdb.AccountGroup;
@@ -26,7 +28,6 @@ import com.google.gerrit.client.rpc.RpcUtil;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtjsonrpc.client.VoidResult; import com.google.gwtjsonrpc.client.VoidResult;
import com.google.gwtorm.client.OrmException; import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.gwtorm.client.Transaction; import com.google.gwtorm.client.Transaction;
import java.util.ArrayList; import java.util.ArrayList;
@@ -39,8 +40,11 @@ import java.util.Set;
public class GroupAdminServiceImpl extends BaseServiceImplementation implements public class GroupAdminServiceImpl extends BaseServiceImplementation implements
GroupAdminService { GroupAdminService {
public GroupAdminServiceImpl(final SchemaFactory<ReviewDb> rdf) { private final AccountGroup.Id adminId;
super(rdf);
public GroupAdminServiceImpl(final GerritServer server) {
super(server.getDatabase());
adminId = server.getAdminGroupId();
} }
public void ownedGroups(final AsyncCallback<List<AccountGroup>> callback) { public void ownedGroups(final AsyncCallback<List<AccountGroup>> callback) {
@@ -68,13 +72,6 @@ public class GroupAdminServiceImpl extends BaseServiceImplementation implements
public AccountGroup.Id run(final ReviewDb db) throws OrmException, public AccountGroup.Id run(final ReviewDb db) throws OrmException,
Failure { Failure {
final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName); final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName);
if (nameKey.equals(ADMIN_GROUP)) {
// Forbid creating the admin group, its highly special because it
// has near root level access to the server, based upon its name.
//
throw new Failure(new NameAlreadyUsedException());
}
if (db.accountGroups().get(nameKey) != null) { if (db.accountGroups().get(nameKey) != null) {
throw new Failure(new NameAlreadyUsedException()); throw new Failure(new NameAlreadyUsedException());
} }
@@ -165,13 +162,6 @@ public class GroupAdminServiceImpl extends BaseServiceImplementation implements
} }
final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName); final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName);
if (group.getName().equals(ADMIN_GROUP) || nameKey.equals(ADMIN_GROUP)) {
// Forbid renaming the admin group, its highly special because it
// has near root level access to the server, based upon its name.
//
throw new Failure(new NameAlreadyUsedException());
}
if (!nameKey.equals(group.getNameKey())) { if (!nameKey.equals(group.getNameKey())) {
if (db.accountGroups().get(nameKey) != null) { if (db.accountGroups().get(nameKey) != null) {
throw new Failure(new NameAlreadyUsedException()); throw new Failure(new NameAlreadyUsedException());
@@ -238,12 +228,11 @@ public class GroupAdminServiceImpl extends BaseServiceImplementation implements
new AccountGroupMember.Key(RpcUtil.getAccountId(), groupId)) != null; new AccountGroupMember.Key(RpcUtil.getAccountId(), groupId)) != null;
} }
private static boolean amAdmin(final ReviewDb db) throws OrmException { private boolean amAdmin(final ReviewDb db) throws OrmException {
final AccountGroup admin = db.accountGroups().get(ADMIN_GROUP); return adminId != null && amInGroup(db, adminId);
return admin != null && amInGroup(db, admin.getId());
} }
private static void assertAmGroupOwner(final ReviewDb db, private void assertAmGroupOwner(final ReviewDb db,
final AccountGroup.Id groupId) throws OrmException, Failure { final AccountGroup.Id groupId) throws OrmException, Failure {
final AccountGroup group = db.accountGroups().get(groupId); final AccountGroup group = db.accountGroups().get(groupId);
if (group == null) { if (group == null) {

View File

@@ -14,12 +14,11 @@
package com.google.gerrit.server; package com.google.gerrit.server;
import com.google.gerrit.client.admin.GroupAdminServiceImpl;
/** Publishes {@link GroupAdminServiceImpl} over JSON. */ /** Publishes {@link GroupAdminServiceImpl} over JSON. */
public class GroupAdminServiceSrv extends GerritJsonServlet { public class GroupAdminServiceSrv extends GerritJsonServlet {
@Override @Override
protected Object createServiceHandle() throws Exception { protected Object createServiceHandle() throws Exception {
return new GroupAdminServiceImpl(GerritServer.getInstance().getDatabase()); return new GroupAdminServiceImpl(GerritServer.getInstance());
} }
} }

View File

@@ -155,11 +155,6 @@ INSERT INTO account_groups
g.name g.name
FROM gerrit1.account_groups g; FROM gerrit1.account_groups g;
UPDATE account_groups
SET owner_group_id = (SELECT group_id
FROM account_groups
WHERE name = 'admin');
DELETE FROM account_group_members; DELETE FROM account_group_members;
INSERT INTO account_group_members INSERT INTO account_group_members
(account_id, (account_id,
@@ -173,6 +168,18 @@ INSERT INTO account_group_members
o.group_name = g.name o.group_name = g.name
AND a.preferred_email = o.email; AND a.preferred_email = o.email;
UPDATE account_groups
SET name = 'Administrators'
WHERE name = 'admin';
UPDATE system_config
SET admin_group_id = (SELECT group_id
FROM account_groups
WHERE name = 'Administrators');
UPDATE account_groups
SET owner_group_id = (SELECT admin_group_id FROM system_config);
DELETE FROM projects; DELETE FROM projects;
INSERT INTO projects INSERT INTO projects
(project_id, (project_id,