Allow users to see what groups they are members of

Knowing what groups a user is in may help a site administrator debug
a specific user's access problems, and it may also help a project
owner to decide which group they want to give out some access for.

Bug: GERRIT-276
Change-Id: Ic06d8d5ba9d96354e47e8eda751c40b1fc360374
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-09-03 11:36:49 -07:00
parent 2f90a2bf2d
commit e04a97ffd2
11 changed files with 149 additions and 7 deletions

View File

@@ -51,6 +51,7 @@ public class Link implements ValueChangeHandler<String> {
public static final String SETTINGS = "settings";
public static final String SETTINGS_SSHKEYS = "settings,ssh-keys";
public static final String SETTINGS_WEBIDENT = "settings,web-identities";
public static final String SETTINGS_MYGROUPS = "settings,group-memberships";
public static final String SETTINGS_AGREEMENTS = "settings,agreements";
public static final String SETTINGS_CONTACT = "settings,contact";
public static final String SETTINGS_PROJECTS = "settings,projects";

View File

@@ -35,6 +35,7 @@ public interface AccountConstants extends Constants {
String tabContactInformation();
String tabSshKeys();
String tabWebIdentities();
String tabMyGroups();
String tabAgreements();
String buttonShowAddSshKey();

View File

@@ -15,6 +15,7 @@ tabPreferences = Preferences
tabContactInformation = Contact Information
tabSshKeys = SSH Keys
tabWebIdentities = Identities
tabMyGroups = Groups
tabAgreements = Agreements
buttonShowAddSshKey = Add Key ...

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.client.account;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.reviewdb.AccountSshKey;
import com.google.gerrit.client.reviewdb.ContactInformation;
import com.google.gerrit.client.reviewdb.ContributorAgreement;
@@ -44,6 +45,9 @@ public interface AccountSecurity extends RemoteJsonService {
@SignInRequired
void myExternalIds(AsyncCallback<List<AccountExternalId>> callback);
@SignInRequired
void myGroups(AsyncCallback<List<AccountGroup>> callback);
@SignInRequired
void deleteExternalIds(Set<AccountExternalId.Key> keys,
AsyncCallback<Set<AccountExternalId.Key>> callback);

View File

@@ -128,6 +128,14 @@ public class AccountSettings extends AccountScreen {
}, Util.C.tabWebIdentities());
tabTokens.add(Link.SETTINGS_WEBIDENT);
tabs.add(new LazyPanel() {
@Override
protected MyGroupsPanel createWidget() {
return new MyGroupsPanel();
}
}, Util.C.tabMyGroups());
tabTokens.add(Link.SETTINGS_MYGROUPS);
if (Gerrit.getConfig().isUseContributorAgreements()) {
tabs.add(new LazyPanel() {
@Override

View File

@@ -0,0 +1,50 @@
// Copyright (C) 2009 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.client.account;
import com.google.gerrit.client.admin.GroupTable;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import java.util.List;
class MyGroupsPanel extends Composite {
private GroupTable groups;
MyGroupsPanel() {
final FlowPanel body = new FlowPanel();
groups = new GroupTable(false /* do not hyperlink to admin */);
body.add(groups);
initWidget(body);
}
@Override
protected void onLoad() {
super.onLoad();
refresh();
}
private void refresh() {
Util.ACCOUNT_SEC.myGroups(new GerritCallback<List<AccountGroup>>() {
public void onSuccess(final List<AccountGroup> result) {
groups.display(result);
}
});
}
}

View File

@@ -53,7 +53,7 @@ public class GroupListScreen extends AccountScreen {
super.onInitUI();
setPageTitle(Util.C.groupListTitle());
groups = new GroupTable(Link.ADMIN_GROUPS);
groups = new GroupTable(true /* hyperlink to admin */, Link.ADMIN_GROUPS);
add(groups);
final VerticalPanel fp = new VerticalPanel();

View File

@@ -29,11 +29,15 @@ import java.util.List;
public class GroupTable extends NavigationTable<AccountGroup> {
public GroupTable() {
this(null);
private final boolean enableLink;
public GroupTable(final boolean enableLink) {
this(enableLink, null);
}
public GroupTable(final String pointerId) {
public GroupTable(final boolean enableLink, final String pointerId) {
this.enableLink = enableLink;
setSavePointerId(pointerId);
keysNavigation.add(new PrevKeyCommand(0, 'k', Util.C.groupListPrev()));
keysNavigation.add(new NextKeyCommand(0, 'j', Util.C.groupListNext()));
@@ -82,8 +86,12 @@ public class GroupTable extends NavigationTable<AccountGroup> {
}
void populate(final int row, final AccountGroup k) {
table.setWidget(row, 1, new Hyperlink(k.getName(), Link.toAccountGroup(k
.getId())));
if (enableLink) {
table.setWidget(row, 1, new Hyperlink(k.getName(), Link.toAccountGroup(k
.getId())));
} else {
table.setText(row, 1, k.getName());
}
table.setText(row, 2, k.getDescription());
final FlexCellFormatter fmt = table.getFlexCellFormatter();

View File

@@ -31,6 +31,7 @@ public class AccountModule extends RpcServletModule {
factory(AgreementInfoFactory.Factory.class);
factory(ExternalIdDetailFactory.Factory.class);
factory(GroupDetailFactory.Factory.class);
factory(MyGroupsFactory.Factory.class);
}
});
rpc(AccountSecurityImpl.class);

View File

@@ -18,6 +18,7 @@ import com.google.gerrit.client.account.AccountSecurity;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountAgreement;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.reviewdb.AccountSshKey;
import com.google.gerrit.client.reviewdb.ContactInformation;
import com.google.gerrit.client.reviewdb.ContributorAgreement;
@@ -78,6 +79,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
private final boolean useContactInfo;
private final ExternalIdDetailFactory.Factory externalIdDetailFactory;
private final MyGroupsFactory.Factory myGroupsFactory;
@Inject
AccountSecurityImpl(final Provider<ReviewDb> schema,
@@ -86,7 +88,8 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
final RegisterNewEmailSender.Factory esf, final SshKeyCache skc,
final AccountByEmailCache abec, final AccountCache uac,
final AccountManager am,
final ExternalIdDetailFactory.Factory externalIdDetailFactory) {
final ExternalIdDetailFactory.Factory externalIdDetailFactory,
final MyGroupsFactory.Factory myGroupsFactory) {
super(schema, currentUser);
contactStore = cs;
authConfig = ac;
@@ -100,6 +103,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
useContactInfo = contactStore != null && contactStore.isEnabled();
this.externalIdDetailFactory = externalIdDetailFactory;
this.myGroupsFactory = myGroupsFactory;
}
public void mySshKeys(final AsyncCallback<List<AccountSshKey>> callback) {
@@ -220,6 +224,11 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
externalIdDetailFactory.create().to(callback);
}
@Override
public void myGroups(final AsyncCallback<List<AccountGroup>> callback) {
myGroupsFactory.create().to(callback);
}
public void deleteExternalIds(final Set<AccountExternalId.Key> keys,
final AsyncCallback<Set<AccountExternalId.Key>> callback) {
run(callback, new Action<Set<AccountExternalId.Key>>() {

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2009 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.rpc.account;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.rpc.Handler;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
class MyGroupsFactory extends Handler<List<AccountGroup>> {
interface Factory {
MyGroupsFactory create();
}
private final GroupCache groupCache;
private final IdentifiedUser user;
@Inject
MyGroupsFactory(final GroupCache groupCache, final IdentifiedUser user) {
this.groupCache = groupCache;
this.user = user;
}
@Override
public List<AccountGroup> call() throws Exception {
final Set<AccountGroup.Id> effective = user.getEffectiveGroups();
final int cnt = effective.size();
final List<AccountGroup> groupList = new ArrayList<AccountGroup>(cnt);
for (final AccountGroup.Id groupId : effective) {
groupList.add(groupCache.get(groupId));
}
Collections.sort(groupList, new Comparator<AccountGroup>() {
@Override
public int compare(AccountGroup a, AccountGroup b) {
return a.getName().compareTo(b.getName());
}
});
return groupList;
}
}