Limit assignee suggestions to users that can see the change

Bug: Issue 5181
Change-Id: Ib64248a285e8feca1fd8f18e825f302d09d252ed
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java
index 06ceb49..7f4522f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountApi.java
@@ -27,6 +27,7 @@
 import com.google.gwt.core.client.JsArray;
 import com.google.gwt.core.client.JsArrayString;
 import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtorm.client.KeyUtil;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -49,7 +50,7 @@
   public static void suggest(String query, int limit, AsyncCallback<JsArray<AccountInfo>> cb) {
     new RestApi("/accounts/")
         .addParameterTrue("suggest")
-        .addParameter("q", query)
+        .addParameterRaw("q", KeyUtil.encode(query))
         .addParameter("n", limit)
         .background()
         .get(cb);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java
index 0fd85f1..a376782 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java
@@ -102,6 +102,7 @@
     this.changeId = info.legacyId();
     this.project = info.projectNameKey();
     this.canEdit = info.hasActions() && info.actions().containsKey("assignee");
+    assigneeSuggestOracle.setChange(info);
     setAssignee(info.assignee());
     editAssigneeIcon.setVisible(canEdit);
     if (!canEdit) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java
index 964f7ad..c8bbfc3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AssigneeSuggestOracle.java
@@ -16,6 +16,7 @@
 
 import com.google.gerrit.client.account.AccountApi;
 import com.google.gerrit.client.info.AccountInfo;
+import com.google.gerrit.client.info.ChangeInfo;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.Natives;
 import com.google.gerrit.client.ui.AccountSuggestOracle.AccountSuggestion;
@@ -27,10 +28,17 @@
 
 /** REST API based suggestion Oracle for assignee */
 public class AssigneeSuggestOracle extends SuggestAfterTypingNCharsOracle {
+
+  private ChangeInfo change;
+
+  public void setChange(ChangeInfo change) {
+    this.change = change;
+  }
+
   @Override
   protected void _onRequestSuggestions(Request req, Callback cb) {
     AccountApi.suggest(
-        req.getQuery(),
+        getQuery(req),
         req.getLimit(),
         new GerritCallback<JsArray<AccountInfo>>() {
           @Override
@@ -49,4 +57,13 @@
           }
         });
   }
+
+  private String getQuery(Request req) {
+    StringBuilder query = new StringBuilder();
+    query.append(req.getQuery());
+    if (change != null) {
+      query.append(" cansee:").append(change._number());
+    }
+    return query.toString();
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
index 55f283e..959f764 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
@@ -162,6 +162,14 @@
   @Override
   protected Predicate<AccountState> defaultField(String query) {
     Predicate<AccountState> defaultPredicate = AccountPredicates.defaultPredicate(query);
+    if (query.startsWith("cansee:")) {
+      try {
+        return cansee(query.substring(7));
+      } catch (OrmException | QueryParseException | PermissionBackendException e) {
+        // Ignore, fall back to default query
+      }
+    }
+
     if ("self".equalsIgnoreCase(query) || "me".equalsIgnoreCase(query)) {
       try {
         return Predicate.or(defaultPredicate, AccountPredicates.id(self()));