Don't allow discovery of non-visible groups

A user could use the ls-members command to distinguish between a
non-existent group and an existent but not visible group:

$ ssh -p29418 johndoe@localhost gerrit ls-members non-existent-group
Group not found or not visible

$ ssh -p29418 johndoe@localhost gerrit ls-members existent-but-not-visible-group
id      username        full name       email

With this fix, the response for both cases is the same:
$ ssh -p29418 johndoe@localhost gerrit ls-members existent-but-not-visible-group
Group not found or not visible

Release-Notes: Don't allow discovery of non-visible groups
Change-Id: I7b67b5ba0eae066485d0ddbd027ac1fc3f95f346
diff --git a/java/com/google/gerrit/server/restapi/group/ListMembers.java b/java/com/google/gerrit/server/restapi/group/ListMembers.java
index c6da92f..6067a66 100644
--- a/java/com/google/gerrit/server/restapi/group/ListMembers.java
+++ b/java/com/google/gerrit/server/restapi/group/ListMembers.java
@@ -78,6 +78,12 @@
     return Response.ok(getDirectMembers(group, resource.getControl()));
   }
 
+  protected boolean canSeeGroup(InternalGroup group) {
+    InternalGroupDescription internalGroup = new InternalGroupDescription(group);
+    GroupControl groupControl = groupControlFactory.controlFor(internalGroup);
+    return groupControl.canSeeGroup();
+  }
+
   public List<AccountInfo> getTransitiveMembers(AccountGroup.UUID groupUuid)
       throws PermissionBackendException {
     Optional<InternalGroup> group = groupCache.get(groupUuid);
diff --git a/java/com/google/gerrit/sshd/commands/ListMembersCommand.java b/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
index fd18656..9c33201 100644
--- a/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
+++ b/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
@@ -74,7 +74,7 @@
       Optional<InternalGroup> group = groupCache.get(AccountGroup.nameKey(name));
       String errorText = "Group not found or not visible\n";
 
-      if (!group.isPresent()) {
+      if (!group.isPresent() || !canSeeGroup(group.get())) {
         writer.write(errorText);
         writer.flush();
         return;