GET /accounts/{id}/groups
Obtain the list of groups a target user is a member of from
within the user resource, rather than /groups/?user={id} query.
This is a different projection of essentially the same data,
but I think it makes sense to allow a user to ask for their
groups within their account.
A nice benefit is we can now ask /accounts/self/groups to see
our own groups at any time, whereas /groups/?user={id} does not
accept self as an argument.
Unlike /groups/?user={id} query any user can see a subset of
another user's groups if two things are true:
- The caller can see the other user.
Often true when both users have a group in common.
- The caller can see the group.
True when the caller is an owner of that group, or
the group is visible to everyone.
- The caller can see the members of the group.
True if the caller is an owner, or the group
is visible to everyone.
Change-Id: I43d43f2f774dafb1f77fd047b50b6fa050f82d07
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
package com.google.gerrit.client.account;
|
package com.google.gerrit.client.account;
|
||||||
|
|
||||||
import com.google.gerrit.client.admin.GroupTable;
|
import com.google.gerrit.client.admin.GroupTable;
|
||||||
import com.google.gerrit.client.groups.GroupMap;
|
import com.google.gerrit.client.groups.GroupList;
|
||||||
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
||||||
|
|
||||||
public class MyGroupsScreen extends SettingsScreen {
|
public class MyGroupsScreen extends SettingsScreen {
|
||||||
@@ -31,9 +31,9 @@ public class MyGroupsScreen extends SettingsScreen {
|
|||||||
@Override
|
@Override
|
||||||
protected void onLoad() {
|
protected void onLoad() {
|
||||||
super.onLoad();
|
super.onLoad();
|
||||||
GroupMap.my(new ScreenLoadCallback<GroupMap>(this) {
|
GroupList.my(new ScreenLoadCallback<GroupList>(this) {
|
||||||
@Override
|
@Override
|
||||||
protected void preDisplay(final GroupMap result) {
|
protected void preDisplay(GroupList result) {
|
||||||
groups.display(result);
|
groups.display(result);
|
||||||
groups.finishDisplay();
|
groups.finishDisplay();
|
||||||
}});
|
}});
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.google.gerrit.client.admin;
|
|||||||
import com.google.gerrit.client.Dispatcher;
|
import com.google.gerrit.client.Dispatcher;
|
||||||
import com.google.gerrit.client.Gerrit;
|
import com.google.gerrit.client.Gerrit;
|
||||||
import com.google.gerrit.client.groups.GroupInfo;
|
import com.google.gerrit.client.groups.GroupInfo;
|
||||||
|
import com.google.gerrit.client.groups.GroupList;
|
||||||
import com.google.gerrit.client.groups.GroupMap;
|
import com.google.gerrit.client.groups.GroupMap;
|
||||||
import com.google.gerrit.client.ui.HighlightingInlineHyperlink;
|
import com.google.gerrit.client.ui.HighlightingInlineHyperlink;
|
||||||
import com.google.gerrit.client.ui.NavigationTable;
|
import com.google.gerrit.client.ui.NavigationTable;
|
||||||
@@ -76,15 +77,18 @@ public class GroupTable extends NavigationTable<GroupInfo> {
|
|||||||
History.newItem(Dispatcher.toGroup(getRowItem(row).getGroupId()));
|
History.newItem(Dispatcher.toGroup(getRowItem(row).getGroupId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void display(final GroupMap groups) {
|
public void display(GroupMap groups, String toHighlight) {
|
||||||
display(groups, null);
|
display(groups.values().asList(), toHighlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void display(final GroupMap groups, final String toHighlight) {
|
public void display(GroupList groups) {
|
||||||
|
display(groups.asList(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void display(List<GroupInfo> list, String toHighlight) {
|
||||||
while (1 < table.getRowCount())
|
while (1 < table.getRowCount())
|
||||||
table.removeRow(table.getRowCount() - 1);
|
table.removeRow(table.getRowCount() - 1);
|
||||||
|
|
||||||
List<GroupInfo> list = groups.values().asList();
|
|
||||||
Collections.sort(list, new Comparator<GroupInfo>() {
|
Collections.sort(list, new Comparator<GroupInfo>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(GroupInfo a, GroupInfo b) {
|
public int compare(GroupInfo a, GroupInfo b) {
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (C) 2013 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.groups;
|
||||||
|
|
||||||
|
import com.google.gerrit.client.rpc.NativeList;
|
||||||
|
import com.google.gerrit.client.rpc.RestApi;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
|
||||||
|
/** Groups available from {@code /groups/} or {@code /accounts/{id}/groups}. */
|
||||||
|
public class GroupList extends NativeList<GroupInfo> {
|
||||||
|
public static void my(AsyncCallback<GroupList> callback) {
|
||||||
|
new RestApi("/accounts/self/groups").get(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GroupList() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
package com.google.gerrit.client.groups;
|
package com.google.gerrit.client.groups;
|
||||||
|
|
||||||
import com.google.gerrit.client.Gerrit;
|
|
||||||
import com.google.gerrit.client.rpc.NativeMap;
|
import com.google.gerrit.client.rpc.NativeMap;
|
||||||
import com.google.gerrit.client.rpc.RestApi;
|
import com.google.gerrit.client.rpc.RestApi;
|
||||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
@@ -26,12 +25,6 @@ public class GroupMap extends NativeMap<GroupInfo> {
|
|||||||
.get(NativeMap.copyKeysIntoChildren(callback));
|
.get(NativeMap.copyKeysIntoChildren(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void my(AsyncCallback<GroupMap> callback) {
|
|
||||||
new RestApi("/groups/")
|
|
||||||
.addParameter("user", Gerrit.getUserAccount().getId().get())
|
|
||||||
.get(NativeMap.copyKeysIntoChildren(callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void match(String match, AsyncCallback<GroupMap> cb) {
|
public static void match(String match, AsyncCallback<GroupMap> cb) {
|
||||||
if (match == null || "".equals(match)) {
|
if (match == null || "".equals(match)) {
|
||||||
all(cb);
|
all(cb);
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (C) 2013 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.account;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||||
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.group.GroupInfo;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class GetGroups implements RestReadView<AccountResource> {
|
||||||
|
private final GroupControl.Factory groupControlFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
GetGroups(GroupControl.Factory groupControlFactory) {
|
||||||
|
this.groupControlFactory = groupControlFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GroupInfo> apply(AccountResource resource) {
|
||||||
|
IdentifiedUser user = resource.getUser();
|
||||||
|
Account.Id userId = user.getAccountId();
|
||||||
|
List<GroupInfo> groups = Lists.newArrayList();
|
||||||
|
for (AccountGroup.UUID uuid : user.getEffectiveGroups().getKnownGroups()) {
|
||||||
|
GroupControl ctl;
|
||||||
|
try {
|
||||||
|
ctl = groupControlFactory.controlFor(uuid);
|
||||||
|
} catch (NoSuchGroupException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ctl.isVisible() && ctl.canSeeMember(userId)) {
|
||||||
|
groups.add(new GroupInfo(ctl.getGroup()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ public class Module extends RestApiModule {
|
|||||||
DynamicMap.mapOf(binder(), CAPABILITY_KIND);
|
DynamicMap.mapOf(binder(), CAPABILITY_KIND);
|
||||||
|
|
||||||
child(ACCOUNT_KIND, "capabilities").to(Capabilities.class);
|
child(ACCOUNT_KIND, "capabilities").to(Capabilities.class);
|
||||||
|
get(ACCOUNT_KIND, "groups").to(GetGroups.class);
|
||||||
get(CAPABILITY_KIND).to(GetCapabilities.CheckOne.class);
|
get(CAPABILITY_KIND).to(GetCapabilities.CheckOne.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,50 +14,15 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.group;
|
package com.google.gerrit.server.group;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.gerrit.common.data.GroupDescription;
|
|
||||||
import com.google.gerrit.extensions.restapi.AuthException;
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
|
||||||
import com.google.gerrit.server.util.Url;
|
|
||||||
|
|
||||||
class GetGroup implements RestReadView<GroupResource> {
|
class GetGroup implements RestReadView<GroupResource> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object apply(GroupResource resource) throws AuthException,
|
public Object apply(GroupResource resource) throws AuthException,
|
||||||
BadRequestException, ResourceConflictException, Exception {
|
BadRequestException, ResourceConflictException, Exception {
|
||||||
return new GroupInfo(resource.getControl().getGroup());
|
return new GroupInfo(resource.getControl().getGroup());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GroupInfo {
|
|
||||||
final String kind = "gerritcodereview#group";
|
|
||||||
String id;
|
|
||||||
String name;
|
|
||||||
Boolean visibleToAll;
|
|
||||||
|
|
||||||
// These fields are only supplied for internal groups.
|
|
||||||
String description;
|
|
||||||
Integer groupId;
|
|
||||||
String ownerId;
|
|
||||||
|
|
||||||
GroupInfo(GroupDescription.Basic group) {
|
|
||||||
id = Url.encode(group.getGroupUUID().get());
|
|
||||||
name = Strings.emptyToNull(group.getName());
|
|
||||||
visibleToAll = group.isVisibleToAll() ? true : null;
|
|
||||||
|
|
||||||
if (group instanceof GroupDescription.Internal) {
|
|
||||||
set(((GroupDescription.Internal) group).getAccountGroup());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void set(AccountGroup d) {
|
|
||||||
description = Strings.emptyToNull(d.getDescription());
|
|
||||||
groupId = d.getId().get();
|
|
||||||
ownerId = d.getOwnerGroupUUID() != null
|
|
||||||
? Url.encode(d.getOwnerGroupUUID().get())
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,10 @@
|
|||||||
package com.google.gerrit.server.group;
|
package com.google.gerrit.server.group;
|
||||||
|
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.server.group.GetGroup.GroupInfo;
|
|
||||||
|
|
||||||
public class GetIncludedGroup implements RestReadView<IncludedGroupResource> {
|
public class GetIncludedGroup implements RestReadView<IncludedGroupResource> {
|
||||||
@Override
|
@Override
|
||||||
public GroupInfo apply(IncludedGroupResource rsrc) {
|
public GroupInfo apply(IncludedGroupResource rsrc) {
|
||||||
return new GetGroup.GroupInfo(rsrc.getGroup());
|
return new GroupInfo(rsrc.getGroup());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (C) 2013 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.group;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.gerrit.common.data.GroupDescription;
|
||||||
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
|
import com.google.gerrit.server.util.Url;
|
||||||
|
|
||||||
|
public class GroupInfo {
|
||||||
|
final String kind = "gerritcodereview#group";
|
||||||
|
public String id;
|
||||||
|
public String name;
|
||||||
|
Boolean visibleToAll;
|
||||||
|
|
||||||
|
// These fields are only supplied for internal groups.
|
||||||
|
String description;
|
||||||
|
Integer groupId;
|
||||||
|
String ownerId;
|
||||||
|
|
||||||
|
public GroupInfo(GroupDescription.Basic group) {
|
||||||
|
id = Url.encode(group.getGroupUUID().get());
|
||||||
|
name = Strings.emptyToNull(group.getName());
|
||||||
|
visibleToAll = group.isVisibleToAll() ? true : null;
|
||||||
|
|
||||||
|
if (group instanceof GroupDescription.Internal) {
|
||||||
|
set(((GroupDescription.Internal) group).getAccountGroup());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void set(AccountGroup d) {
|
||||||
|
description = Strings.emptyToNull(d.getDescription());
|
||||||
|
groupId = d.getId().get();
|
||||||
|
ownerId = d.getOwnerGroupUUID() != null
|
||||||
|
? Url.encode(d.getOwnerGroupUUID().get())
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,6 @@ import com.google.gerrit.server.IdentifiedUser;
|
|||||||
import com.google.gerrit.server.OutputFormat;
|
import com.google.gerrit.server.OutputFormat;
|
||||||
import com.google.gerrit.server.account.GroupCache;
|
import com.google.gerrit.server.account.GroupCache;
|
||||||
import com.google.gerrit.server.account.VisibleGroups;
|
import com.google.gerrit.server.account.VisibleGroups;
|
||||||
import com.google.gerrit.server.group.GetGroup.GroupInfo;
|
|
||||||
import com.google.gerrit.server.ioutil.ColumnFormatter;
|
import com.google.gerrit.server.ioutil.ColumnFormatter;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
|
|||||||
import com.google.gerrit.reviewdb.client.AccountGroupIncludeByUuid;
|
import com.google.gerrit.reviewdb.client.AccountGroupIncludeByUuid;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.account.GroupControl;
|
import com.google.gerrit.server.account.GroupControl;
|
||||||
import com.google.gerrit.server.group.GetGroup.GroupInfo;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
@@ -63,7 +62,7 @@ public class ListIncludedGroups implements RestReadView<GroupResource> {
|
|||||||
try {
|
try {
|
||||||
GroupControl i = controlFactory.controlFor(u.getIncludeUUID());
|
GroupControl i = controlFactory.controlFor(u.getIncludeUUID());
|
||||||
if (ownerOfParent || i.isVisible()) {
|
if (ownerOfParent || i.isVisible()) {
|
||||||
included.add(new GetGroup.GroupInfo(i.getGroup()));
|
included.add(new GroupInfo(i.getGroup()));
|
||||||
}
|
}
|
||||||
} catch (NoSuchGroupException notFound) {
|
} catch (NoSuchGroupException notFound) {
|
||||||
log.warn(String.format("Group %s no longer available, included into ",
|
log.warn(String.format("Group %s no longer available, included into ",
|
||||||
|
|||||||
Reference in New Issue
Block a user