Return only exact matches from InternalAccountQuery#byPreferredEmail
Doing an account query on the preferredemail field finds accounts with a
preferred email that matches the given email case insensitive or that
starts with that prefix (also case insensitive). However all callers are
only interested in exact matches. Instead of letting each caller filter
out non-exact matches do this filtering once in
InternalAccountQuery#byPreferredEmail.
Change-Id: If893d1bd8857fd69b3c2222ba104aa9ee212f936
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
index 4f7a5ba..01aec6e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
@@ -223,8 +223,6 @@
.get()
.byPreferredEmail(email)
.stream()
- // the index query also matches prefixes, filter those out
- .filter(a -> email.equalsIgnoreCase(a.getAccount().getPreferredEmail()))
.map(AccountState::getAccount)
.findFirst();
return match.isPresent() ? auth(match.get()) : null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/Emails.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/Emails.java
index db707a8..3e97265 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/Emails.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/Emails.java
@@ -27,7 +27,6 @@
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
-import java.util.List;
/** Class to access accounts by email. */
@Singleton
@@ -61,15 +60,9 @@
* @see #getAccountsFor(String...)
*/
public ImmutableSet<Account.Id> getAccountFor(String email) throws IOException, OrmException {
- List<AccountState> byPreferredEmail = queryProvider.get().byPreferredEmail(email);
return Streams.concat(
externalIds.byEmail(email).stream().map(e -> e.accountId()),
- byPreferredEmail
- .stream()
- // the index query also matches prefixes and emails with other case,
- // filter those out
- .filter(a -> email.equals(a.getAccount().getPreferredEmail()))
- .map(a -> a.getAccount().getId()))
+ queryProvider.get().byPreferredEmail(email).stream().map(a -> a.getAccount().getId()))
.collect(toImmutableSet());
}
@@ -91,9 +84,6 @@
.byPreferredEmail(emails)
.entries()
.stream()
- // the index query also matches prefixes and emails with other case,
- // filter those out
- .filter(e -> e.getKey().equals(e.getValue().getAccount().getPreferredEmail()))
.forEach(e -> builder.put(e.getKey(), e.getValue().getAccount().getId()));
return builder.build();
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/account/InternalAccountQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/account/InternalAccountQuery.java
index 4821e6f..c76fa12 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/account/InternalAccountQuery.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/account/InternalAccountQuery.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.query.account;
import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
@@ -113,17 +114,41 @@
return query(AccountPredicates.fullName(fullName));
}
+ /**
+ * Queries for accounts that have a preferred email that exactly matches the given email.
+ *
+ * @param email preferred email by which accounts should be found
+ * @return list of accounts that have a preferred email that exactly matches the given email
+ * @throws OrmException if query cannot be parsed
+ */
public List<AccountState> byPreferredEmail(String email) throws OrmException {
- return query(AccountPredicates.preferredEmail(email));
+ return query(AccountPredicates.preferredEmail(email))
+ .stream()
+ .filter(a -> a.getAccount().getPreferredEmail().equals(email))
+ .collect(toList());
}
+ /**
+ * Makes multiple queries for accounts by preferred email (exact match).
+ *
+ * @param emails preferred emails by which accounts should be found
+ * @return multimap of the given emails to accounts that have a preferred email that exactly
+ * matches this email
+ * @throws OrmException if query cannot be parsed
+ */
public Multimap<String, AccountState> byPreferredEmail(String... emails) throws OrmException {
List<String> emailList = Arrays.asList(emails);
List<List<AccountState>> r =
query(emailList.stream().map(e -> AccountPredicates.preferredEmail(e)).collect(toList()));
Multimap<String, AccountState> accountsByEmail = ArrayListMultimap.create();
for (int i = 0; i < emailList.size(); i++) {
- accountsByEmail.putAll(emailList.get(i), r.get(i));
+ String email = emailList.get(i);
+ Set<AccountState> matchingAccounts =
+ r.get(i)
+ .stream()
+ .filter(a -> a.getAccount().getPreferredEmail().equals(email))
+ .collect(toSet());
+ accountsByEmail.putAll(email, matchingAccounts);
}
return accountsByEmail;
}