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:
@@ -51,6 +51,7 @@ public class Link implements ValueChangeHandler<String> {
|
|||||||
public static final String SETTINGS = "settings";
|
public static final String SETTINGS = "settings";
|
||||||
public static final String SETTINGS_SSHKEYS = "settings,ssh-keys";
|
public static final String SETTINGS_SSHKEYS = "settings,ssh-keys";
|
||||||
public static final String SETTINGS_WEBIDENT = "settings,web-identities";
|
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_AGREEMENTS = "settings,agreements";
|
||||||
public static final String SETTINGS_CONTACT = "settings,contact";
|
public static final String SETTINGS_CONTACT = "settings,contact";
|
||||||
public static final String SETTINGS_PROJECTS = "settings,projects";
|
public static final String SETTINGS_PROJECTS = "settings,projects";
|
||||||
|
@@ -35,6 +35,7 @@ public interface AccountConstants extends Constants {
|
|||||||
String tabContactInformation();
|
String tabContactInformation();
|
||||||
String tabSshKeys();
|
String tabSshKeys();
|
||||||
String tabWebIdentities();
|
String tabWebIdentities();
|
||||||
|
String tabMyGroups();
|
||||||
String tabAgreements();
|
String tabAgreements();
|
||||||
|
|
||||||
String buttonShowAddSshKey();
|
String buttonShowAddSshKey();
|
||||||
|
@@ -15,6 +15,7 @@ tabPreferences = Preferences
|
|||||||
tabContactInformation = Contact Information
|
tabContactInformation = Contact Information
|
||||||
tabSshKeys = SSH Keys
|
tabSshKeys = SSH Keys
|
||||||
tabWebIdentities = Identities
|
tabWebIdentities = Identities
|
||||||
|
tabMyGroups = Groups
|
||||||
tabAgreements = Agreements
|
tabAgreements = Agreements
|
||||||
|
|
||||||
buttonShowAddSshKey = Add Key ...
|
buttonShowAddSshKey = Add Key ...
|
||||||
|
@@ -16,6 +16,7 @@ package com.google.gerrit.client.account;
|
|||||||
|
|
||||||
import com.google.gerrit.client.reviewdb.Account;
|
import com.google.gerrit.client.reviewdb.Account;
|
||||||
import com.google.gerrit.client.reviewdb.AccountExternalId;
|
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.AccountSshKey;
|
||||||
import com.google.gerrit.client.reviewdb.ContactInformation;
|
import com.google.gerrit.client.reviewdb.ContactInformation;
|
||||||
import com.google.gerrit.client.reviewdb.ContributorAgreement;
|
import com.google.gerrit.client.reviewdb.ContributorAgreement;
|
||||||
@@ -44,6 +45,9 @@ public interface AccountSecurity extends RemoteJsonService {
|
|||||||
@SignInRequired
|
@SignInRequired
|
||||||
void myExternalIds(AsyncCallback<List<AccountExternalId>> callback);
|
void myExternalIds(AsyncCallback<List<AccountExternalId>> callback);
|
||||||
|
|
||||||
|
@SignInRequired
|
||||||
|
void myGroups(AsyncCallback<List<AccountGroup>> callback);
|
||||||
|
|
||||||
@SignInRequired
|
@SignInRequired
|
||||||
void deleteExternalIds(Set<AccountExternalId.Key> keys,
|
void deleteExternalIds(Set<AccountExternalId.Key> keys,
|
||||||
AsyncCallback<Set<AccountExternalId.Key>> callback);
|
AsyncCallback<Set<AccountExternalId.Key>> callback);
|
||||||
|
@@ -128,6 +128,14 @@ public class AccountSettings extends AccountScreen {
|
|||||||
}, Util.C.tabWebIdentities());
|
}, Util.C.tabWebIdentities());
|
||||||
tabTokens.add(Link.SETTINGS_WEBIDENT);
|
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()) {
|
if (Gerrit.getConfig().isUseContributorAgreements()) {
|
||||||
tabs.add(new LazyPanel() {
|
tabs.add(new LazyPanel() {
|
||||||
@Override
|
@Override
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -53,7 +53,7 @@ public class GroupListScreen extends AccountScreen {
|
|||||||
super.onInitUI();
|
super.onInitUI();
|
||||||
setPageTitle(Util.C.groupListTitle());
|
setPageTitle(Util.C.groupListTitle());
|
||||||
|
|
||||||
groups = new GroupTable(Link.ADMIN_GROUPS);
|
groups = new GroupTable(true /* hyperlink to admin */, Link.ADMIN_GROUPS);
|
||||||
add(groups);
|
add(groups);
|
||||||
|
|
||||||
final VerticalPanel fp = new VerticalPanel();
|
final VerticalPanel fp = new VerticalPanel();
|
||||||
|
@@ -29,11 +29,15 @@ import java.util.List;
|
|||||||
|
|
||||||
|
|
||||||
public class GroupTable extends NavigationTable<AccountGroup> {
|
public class GroupTable extends NavigationTable<AccountGroup> {
|
||||||
public GroupTable() {
|
private final boolean enableLink;
|
||||||
this(null);
|
|
||||||
|
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);
|
setSavePointerId(pointerId);
|
||||||
keysNavigation.add(new PrevKeyCommand(0, 'k', Util.C.groupListPrev()));
|
keysNavigation.add(new PrevKeyCommand(0, 'k', Util.C.groupListPrev()));
|
||||||
keysNavigation.add(new NextKeyCommand(0, 'j', Util.C.groupListNext()));
|
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) {
|
void populate(final int row, final AccountGroup k) {
|
||||||
|
if (enableLink) {
|
||||||
table.setWidget(row, 1, new Hyperlink(k.getName(), Link.toAccountGroup(k
|
table.setWidget(row, 1, new Hyperlink(k.getName(), Link.toAccountGroup(k
|
||||||
.getId())));
|
.getId())));
|
||||||
|
} else {
|
||||||
|
table.setText(row, 1, k.getName());
|
||||||
|
}
|
||||||
table.setText(row, 2, k.getDescription());
|
table.setText(row, 2, k.getDescription());
|
||||||
|
|
||||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||||
|
@@ -31,6 +31,7 @@ public class AccountModule extends RpcServletModule {
|
|||||||
factory(AgreementInfoFactory.Factory.class);
|
factory(AgreementInfoFactory.Factory.class);
|
||||||
factory(ExternalIdDetailFactory.Factory.class);
|
factory(ExternalIdDetailFactory.Factory.class);
|
||||||
factory(GroupDetailFactory.Factory.class);
|
factory(GroupDetailFactory.Factory.class);
|
||||||
|
factory(MyGroupsFactory.Factory.class);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
rpc(AccountSecurityImpl.class);
|
rpc(AccountSecurityImpl.class);
|
||||||
|
@@ -18,6 +18,7 @@ import com.google.gerrit.client.account.AccountSecurity;
|
|||||||
import com.google.gerrit.client.reviewdb.Account;
|
import com.google.gerrit.client.reviewdb.Account;
|
||||||
import com.google.gerrit.client.reviewdb.AccountAgreement;
|
import com.google.gerrit.client.reviewdb.AccountAgreement;
|
||||||
import com.google.gerrit.client.reviewdb.AccountExternalId;
|
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.AccountSshKey;
|
||||||
import com.google.gerrit.client.reviewdb.ContactInformation;
|
import com.google.gerrit.client.reviewdb.ContactInformation;
|
||||||
import com.google.gerrit.client.reviewdb.ContributorAgreement;
|
import com.google.gerrit.client.reviewdb.ContributorAgreement;
|
||||||
@@ -78,6 +79,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
|||||||
private final boolean useContactInfo;
|
private final boolean useContactInfo;
|
||||||
|
|
||||||
private final ExternalIdDetailFactory.Factory externalIdDetailFactory;
|
private final ExternalIdDetailFactory.Factory externalIdDetailFactory;
|
||||||
|
private final MyGroupsFactory.Factory myGroupsFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AccountSecurityImpl(final Provider<ReviewDb> schema,
|
AccountSecurityImpl(final Provider<ReviewDb> schema,
|
||||||
@@ -86,7 +88,8 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
|||||||
final RegisterNewEmailSender.Factory esf, final SshKeyCache skc,
|
final RegisterNewEmailSender.Factory esf, final SshKeyCache skc,
|
||||||
final AccountByEmailCache abec, final AccountCache uac,
|
final AccountByEmailCache abec, final AccountCache uac,
|
||||||
final AccountManager am,
|
final AccountManager am,
|
||||||
final ExternalIdDetailFactory.Factory externalIdDetailFactory) {
|
final ExternalIdDetailFactory.Factory externalIdDetailFactory,
|
||||||
|
final MyGroupsFactory.Factory myGroupsFactory) {
|
||||||
super(schema, currentUser);
|
super(schema, currentUser);
|
||||||
contactStore = cs;
|
contactStore = cs;
|
||||||
authConfig = ac;
|
authConfig = ac;
|
||||||
@@ -100,6 +103,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
|||||||
useContactInfo = contactStore != null && contactStore.isEnabled();
|
useContactInfo = contactStore != null && contactStore.isEnabled();
|
||||||
|
|
||||||
this.externalIdDetailFactory = externalIdDetailFactory;
|
this.externalIdDetailFactory = externalIdDetailFactory;
|
||||||
|
this.myGroupsFactory = myGroupsFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mySshKeys(final AsyncCallback<List<AccountSshKey>> callback) {
|
public void mySshKeys(final AsyncCallback<List<AccountSshKey>> callback) {
|
||||||
@@ -220,6 +224,11 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
|
|||||||
externalIdDetailFactory.create().to(callback);
|
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,
|
public void deleteExternalIds(final Set<AccountExternalId.Key> keys,
|
||||||
final AsyncCallback<Set<AccountExternalId.Key>> callback) {
|
final AsyncCallback<Set<AccountExternalId.Key>> callback) {
|
||||||
run(callback, new Action<Set<AccountExternalId.Key>>() {
|
run(callback, new Action<Set<AccountExternalId.Key>>() {
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user