Merge "ListGroups: Add support to list groups by owner"
This commit is contained in:
@@ -124,6 +124,40 @@ client so they are generally disabled by default. Optional fields are:
|
||||
* `MEMBERS`: include list of direct group members.
|
||||
--
|
||||
|
||||
==== Find groups that are owned by another group
|
||||
|
||||
By setting `ownedBy` and specifying the link:#group-id[\{group-id\}] of another
|
||||
group, it is possible to find all the groups for which the owning group is the
|
||||
given group.
|
||||
|
||||
.Request
|
||||
----
|
||||
GET /groups/?ownedBy=7ca042f4d5847936fcb90ca91057673157fd06fc HTTP/1.0
|
||||
----
|
||||
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"MyProject-Committers": {
|
||||
"id": "9999c971bb4ab872aab759d8c49833ee6b9ff320",
|
||||
"url": "#/admin/groups/uuid-9999c971bb4ab872aab759d8c49833ee6b9ff320",
|
||||
"options": {
|
||||
"visible_to_all": true
|
||||
},
|
||||
"description":"contains all committers for MyProject",
|
||||
"group_id": 551,
|
||||
"owner": "MyProject-Owners",
|
||||
"owner_id": "7ca042f4d5847936fcb90ca91057673157fd06fc",
|
||||
"created_on": "2013-02-01 09:59:32.126000000"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
==== Check if a group is owned by the calling user
|
||||
By setting the option `owned` and specifying a group to inspect with
|
||||
the option `group`/`g`, it is possible to find out if this group is
|
||||
|
@@ -490,6 +490,33 @@ public class GroupsIT extends AbstractDaemonTest {
|
||||
.inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGroupsByOwner() throws Exception {
|
||||
String parent = createGroup("test-parent");
|
||||
List<String> children =
|
||||
Arrays.asList(createGroup("test-child1", parent), createGroup("test-child2", parent));
|
||||
|
||||
// By UUID
|
||||
List<GroupInfo> owned =
|
||||
gApi.groups().list().withOwnedBy(getFromCache(parent).getGroupUUID().get()).get();
|
||||
assertThat(owned.stream().map(g -> g.name).collect(toList()))
|
||||
.containsExactlyElementsIn(children);
|
||||
|
||||
// By name
|
||||
owned = gApi.groups().list().withOwnedBy(parent).get();
|
||||
assertThat(owned.stream().map(g -> g.name).collect(toList()))
|
||||
.containsExactlyElementsIn(children);
|
||||
|
||||
// By group that does not own any others
|
||||
owned = gApi.groups().list().withOwnedBy(owned.get(0).id).get();
|
||||
assertThat(owned).isEmpty();
|
||||
|
||||
// By non-existing group
|
||||
exception.expect(UnprocessableEntityException.class);
|
||||
exception.expectMessage("Group Not Found: does-not-exist");
|
||||
gApi.groups().list().withOwnedBy("does-not-exist").get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onlyVisibleGroupsReturned() throws Exception {
|
||||
String newGroupName = name("newGroup");
|
||||
|
@@ -80,6 +80,7 @@ public interface Groups {
|
||||
private String substring;
|
||||
private String suggest;
|
||||
private String regex;
|
||||
private String ownedBy;
|
||||
|
||||
public List<GroupInfo> get() throws RestApiException {
|
||||
Map<String, GroupInfo> map = getAsMap();
|
||||
@@ -160,6 +161,11 @@ public interface Groups {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListRequest withOwnedBy(String ownedBy) {
|
||||
this.ownedBy = ownedBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EnumSet<ListGroupsOption> getOptions() {
|
||||
return options;
|
||||
}
|
||||
@@ -203,6 +209,10 @@ public interface Groups {
|
||||
public String getSuggest() {
|
||||
return suggest;
|
||||
}
|
||||
|
||||
public String getOwnedBy() {
|
||||
return ownedBy;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -133,6 +133,10 @@ class GroupsImpl implements Groups {
|
||||
|
||||
list.setVisibleToAll(req.getVisibleToAll());
|
||||
|
||||
if (req.getOwnedBy() != null) {
|
||||
list.setOwnedBy(req.getOwnedBy());
|
||||
}
|
||||
|
||||
if (req.getUser() != null) {
|
||||
try {
|
||||
list.setUser(accounts.parse(req.getUser()).getAccountId());
|
||||
|
@@ -28,6 +28,7 @@ import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||
import com.google.gerrit.extensions.client.ListGroupsOption;
|
||||
import com.google.gerrit.extensions.common.GroupInfo;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
@@ -55,6 +56,7 @@ import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import org.kohsuke.args4j.Option;
|
||||
@@ -76,6 +78,7 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
private final GroupJson json;
|
||||
private final GroupBackend groupBackend;
|
||||
private final Groups groups;
|
||||
private final GroupsCollection groupsCollection;
|
||||
private final Provider<ReviewDb> db;
|
||||
|
||||
private EnumSet<ListGroupsOption> options = EnumSet.noneOf(ListGroupsOption.class);
|
||||
@@ -87,6 +90,7 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
private String matchSubstring;
|
||||
private String matchRegex;
|
||||
private String suggest;
|
||||
private String ownedBy;
|
||||
|
||||
@Option(
|
||||
name = "--project",
|
||||
@@ -208,6 +212,11 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
options.addAll(ListGroupsOption.fromBits(Integer.parseInt(hex, 16)));
|
||||
}
|
||||
|
||||
@Option(name = "--owned-by", usage = "list groups owned by the given group uuid")
|
||||
public void setOwnedBy(String ownedBy) {
|
||||
this.ownedBy = ownedBy;
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected ListGroups(
|
||||
final GroupCache groupCache,
|
||||
@@ -216,6 +225,7 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
final Provider<IdentifiedUser> identifiedUser,
|
||||
final IdentifiedUser.GenericFactory userFactory,
|
||||
final GetGroups accountGetGroups,
|
||||
final GroupsCollection groupsCollection,
|
||||
GroupJson json,
|
||||
GroupBackend groupBackend,
|
||||
Groups groups,
|
||||
@@ -229,6 +239,7 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
this.json = json;
|
||||
this.groupBackend = groupBackend;
|
||||
this.groups = groups;
|
||||
this.groupsCollection = groupsCollection;
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
@@ -246,7 +257,7 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
|
||||
@Override
|
||||
public SortedMap<String, GroupInfo> apply(TopLevelResource resource)
|
||||
throws OrmException, BadRequestException {
|
||||
throws OrmException, RestApiException {
|
||||
SortedMap<String, GroupInfo> output = new TreeMap<>();
|
||||
for (GroupInfo info : get()) {
|
||||
output.put(MoreObjects.firstNonNull(info.name, "Group " + Url.decode(info.id)), info);
|
||||
@@ -255,7 +266,7 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
return output;
|
||||
}
|
||||
|
||||
public List<GroupInfo> get() throws OrmException, BadRequestException {
|
||||
public List<GroupInfo> get() throws OrmException, RestApiException {
|
||||
if (!Strings.isNullOrEmpty(suggest)) {
|
||||
return suggestGroups();
|
||||
}
|
||||
@@ -264,6 +275,10 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
throw new BadRequestException("Specify one of m/r");
|
||||
}
|
||||
|
||||
if (ownedBy != null) {
|
||||
return getGroupsOwnedBy(ownedBy);
|
||||
}
|
||||
|
||||
if (owned) {
|
||||
return getGroupsOwnedBy(user != null ? userFactory.create(user) : identifiedUser.get());
|
||||
}
|
||||
@@ -345,6 +360,9 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
if (owned) {
|
||||
return true;
|
||||
}
|
||||
if (ownedBy != null) {
|
||||
return true;
|
||||
}
|
||||
if (start != 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -360,14 +378,15 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<GroupInfo> getGroupsOwnedBy(IdentifiedUser user) throws OrmException {
|
||||
private List<GroupInfo> filterGroupsOwnedBy(Predicate<GroupDescription.Internal> filter)
|
||||
throws OrmException {
|
||||
Pattern pattern = getRegexPattern();
|
||||
Stream<GroupDescription.Internal> foundGroups =
|
||||
groups
|
||||
.getAll(db.get())
|
||||
.map(GroupDescriptions::forAccountGroup)
|
||||
.filter(group -> !isNotRelevant(pattern, group))
|
||||
.filter(group -> isOwner(user, group))
|
||||
.filter(filter)
|
||||
.sorted(GROUP_COMPARATOR)
|
||||
.skip(start);
|
||||
if (limit > 0) {
|
||||
@@ -381,6 +400,15 @@ public class ListGroups implements RestReadView<TopLevelResource> {
|
||||
return groupInfos;
|
||||
}
|
||||
|
||||
private List<GroupInfo> getGroupsOwnedBy(String id) throws OrmException, RestApiException {
|
||||
String uuid = groupsCollection.parse(id).getGroupUUID().get();
|
||||
return filterGroupsOwnedBy(group -> group.getOwnerGroupUUID().get().equals(uuid));
|
||||
}
|
||||
|
||||
private List<GroupInfo> getGroupsOwnedBy(IdentifiedUser user) throws OrmException {
|
||||
return filterGroupsOwnedBy(group -> isOwner(user, group));
|
||||
}
|
||||
|
||||
private boolean isOwner(CurrentUser user, GroupDescription.Internal group) {
|
||||
try {
|
||||
return genericGroupControlFactory.controlFor(user, group.getGroupUUID()).isOwner();
|
||||
|
Reference in New Issue
Block a user