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:
@@ -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());
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user