Require account index and remove fallbacks
The account data is moved from ReviewDb into git. Change-Id: I643827179b24601b138f394cfff5890f919b9da9 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -30,7 +30,6 @@ import com.google.common.collect.ImmutableMap;
|
|||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
import com.google.gerrit.acceptance.GerritConfig;
|
|
||||||
import com.google.gerrit.acceptance.GitUtil;
|
import com.google.gerrit.acceptance.GitUtil;
|
||||||
import com.google.gerrit.acceptance.PushOneCommit;
|
import com.google.gerrit.acceptance.PushOneCommit;
|
||||||
import com.google.gerrit.acceptance.TestAccount;
|
import com.google.gerrit.acceptance.TestAccount;
|
||||||
@@ -957,14 +956,6 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
|||||||
pushWithReviewerInFooter("Notauser", null);
|
pushWithReviewerInFooter("Notauser", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
// TODO(dborowitz): This is to exercise a specific case in the database search
|
|
||||||
// path. Once the account index becomes obligatory this method can be removed.
|
|
||||||
@GerritConfig(name = "index.testDisable", value = "accounts")
|
|
||||||
public void pushWithNameInFooterNotFoundWithDbSearch() throws Exception {
|
|
||||||
pushWithReviewerInFooter("Notauser", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pushNewPatchsetOverridingStickyLabel() throws Exception {
|
public void pushNewPatchsetOverridingStickyLabel() throws Exception {
|
||||||
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
|
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
|
||||||
|
@@ -23,12 +23,10 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.common.io.BaseEncoding;
|
import com.google.common.io.BaseEncoding;
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.account.AccountState;
|
import com.google.gerrit.server.account.AccountState;
|
||||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -63,8 +61,6 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class Factory {
|
public static class Factory {
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
private final String webUrl;
|
private final String webUrl;
|
||||||
private final IdentifiedUser.GenericFactory userFactory;
|
private final IdentifiedUser.GenericFactory userFactory;
|
||||||
@@ -73,13 +69,9 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Factory(@GerritServerConfig Config cfg,
|
Factory(@GerritServerConfig Config cfg,
|
||||||
Provider<ReviewDb> db,
|
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider,
|
Provider<InternalAccountQuery> accountQueryProvider,
|
||||||
IdentifiedUser.GenericFactory userFactory,
|
IdentifiedUser.GenericFactory userFactory,
|
||||||
@CanonicalWebUrl String webUrl) {
|
@CanonicalWebUrl String webUrl) {
|
||||||
this.db = db;
|
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
this.webUrl = webUrl;
|
this.webUrl = webUrl;
|
||||||
this.userFactory = userFactory;
|
this.userFactory = userFactory;
|
||||||
@@ -113,8 +105,6 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
private final String webUrl;
|
private final String webUrl;
|
||||||
private final IdentifiedUser.GenericFactory userFactory;
|
private final IdentifiedUser.GenericFactory userFactory;
|
||||||
@@ -122,8 +112,6 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
|
|||||||
private IdentifiedUser expectedUser;
|
private IdentifiedUser expectedUser;
|
||||||
|
|
||||||
private GerritPublicKeyChecker(Factory factory) {
|
private GerritPublicKeyChecker(Factory factory) {
|
||||||
this.db = factory.db;
|
|
||||||
this.accountIndexes = factory.accountIndexes;
|
|
||||||
this.accountQueryProvider = factory.accountQueryProvider;
|
this.accountQueryProvider = factory.accountQueryProvider;
|
||||||
this.webUrl = factory.webUrl;
|
this.webUrl = factory.webUrl;
|
||||||
this.userFactory = factory.userFactory;
|
this.userFactory = factory.userFactory;
|
||||||
@@ -174,8 +162,6 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
|
|||||||
|
|
||||||
private CheckResult checkIdsForArbitraryUser(PGPPublicKey key)
|
private CheckResult checkIdsForArbitraryUser(PGPPublicKey key)
|
||||||
throws PGPException, OrmException {
|
throws PGPException, OrmException {
|
||||||
IdentifiedUser user;
|
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
List<AccountState> accountStates =
|
List<AccountState> accountStates =
|
||||||
accountQueryProvider.get().byExternalId(toExtIdKey(key).get());
|
accountQueryProvider.get().byExternalId(toExtIdKey(key).get());
|
||||||
if (accountStates.isEmpty()) {
|
if (accountStates.isEmpty()) {
|
||||||
@@ -184,15 +170,7 @@ public class GerritPublicKeyChecker extends PublicKeyChecker {
|
|||||||
if (accountStates.size() > 1) {
|
if (accountStates.size() > 1) {
|
||||||
return CheckResult.bad("Key is associated with multiple users");
|
return CheckResult.bad("Key is associated with multiple users");
|
||||||
}
|
}
|
||||||
user = userFactory.create(accountStates.get(0));
|
IdentifiedUser user = userFactory.create(accountStates.get(0));
|
||||||
} else {
|
|
||||||
AccountExternalId extId = db.get().accountExternalIds().get(
|
|
||||||
toExtIdKey(key));
|
|
||||||
if (extId == null) {
|
|
||||||
return CheckResult.bad("Key is not associated with any users");
|
|
||||||
}
|
|
||||||
user = userFactory.create(extId.getAccountId());
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> allowedUserIds = getAllowedUserIds(user);
|
Set<String> allowedUserIds = getAllowedUserIds(user);
|
||||||
if (allowedUserIds.isEmpty()) {
|
if (allowedUserIds.isEmpty()) {
|
||||||
|
@@ -47,7 +47,6 @@ import com.google.gerrit.server.IdentifiedUser;
|
|||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.account.AccountResource;
|
import com.google.gerrit.server.account.AccountResource;
|
||||||
import com.google.gerrit.server.account.AccountState;
|
import com.google.gerrit.server.account.AccountState;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.mail.send.AddKeySender;
|
import com.google.gerrit.server.mail.send.AddKeySender;
|
||||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@@ -90,7 +89,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
|||||||
private final GerritPublicKeyChecker.Factory checkerFactory;
|
private final GerritPublicKeyChecker.Factory checkerFactory;
|
||||||
private final AddKeySender.Factory addKeyFactory;
|
private final AddKeySender.Factory addKeyFactory;
|
||||||
private final AccountCache accountCache;
|
private final AccountCache accountCache;
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -101,7 +99,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
|||||||
GerritPublicKeyChecker.Factory checkerFactory,
|
GerritPublicKeyChecker.Factory checkerFactory,
|
||||||
AddKeySender.Factory addKeyFactory,
|
AddKeySender.Factory addKeyFactory,
|
||||||
AccountCache accountCache,
|
AccountCache accountCache,
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
Provider<InternalAccountQuery> accountQueryProvider) {
|
||||||
this.serverIdent = serverIdent;
|
this.serverIdent = serverIdent;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
@@ -110,7 +107,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
|||||||
this.checkerFactory = checkerFactory;
|
this.checkerFactory = checkerFactory;
|
||||||
this.addKeyFactory = addKeyFactory;
|
this.addKeyFactory = addKeyFactory;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +127,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
|||||||
for (PGPPublicKeyRing keyRing : newKeys) {
|
for (PGPPublicKeyRing keyRing : newKeys) {
|
||||||
PGPPublicKey key = keyRing.getPublicKey();
|
PGPPublicKey key = keyRing.getPublicKey();
|
||||||
AccountExternalId.Key extIdKey = toExtIdKey(key.getFingerprint());
|
AccountExternalId.Key extIdKey = toExtIdKey(key.getFingerprint());
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
Account account = getAccountByExternalId(extIdKey.get());
|
Account account = getAccountByExternalId(extIdKey.get());
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
if (!account.getId().equals(rsrc.getUser().getAccountId())) {
|
if (!account.getId().equals(rsrc.getUser().getAccountId())) {
|
||||||
@@ -142,18 +137,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
|||||||
newExtIds.add(
|
newExtIds.add(
|
||||||
new AccountExternalId(rsrc.getUser().getAccountId(), extIdKey));
|
new AccountExternalId(rsrc.getUser().getAccountId(), extIdKey));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
AccountExternalId existing = db.get().accountExternalIds().get(extIdKey);
|
|
||||||
if (existing != null) {
|
|
||||||
if (!existing.getAccountId().equals(rsrc.getUser().getAccountId())) {
|
|
||||||
throw new ResourceConflictException(
|
|
||||||
"GPG key already associated with another account");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newExtIds.add(
|
|
||||||
new AccountExternalId(rsrc.getUser().getAccountId(), extIdKey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
storeKeys(rsrc, newKeys, toRemove);
|
storeKeys(rsrc, newKeys, toRemove);
|
||||||
|
@@ -28,20 +28,9 @@ public interface AccountExternalIdAccess extends
|
|||||||
@PrimaryKey("key")
|
@PrimaryKey("key")
|
||||||
AccountExternalId get(AccountExternalId.Key key) throws OrmException;
|
AccountExternalId get(AccountExternalId.Key key) throws OrmException;
|
||||||
|
|
||||||
@Query("WHERE key >= ? AND key <= ? ORDER BY key LIMIT ?")
|
|
||||||
ResultSet<AccountExternalId> suggestByKey(AccountExternalId.Key keyA,
|
|
||||||
AccountExternalId.Key keyB, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE accountId = ?")
|
@Query("WHERE accountId = ?")
|
||||||
ResultSet<AccountExternalId> byAccount(Account.Id id) throws OrmException;
|
ResultSet<AccountExternalId> byAccount(Account.Id id) throws OrmException;
|
||||||
|
|
||||||
@Query("WHERE emailAddress = ?")
|
|
||||||
ResultSet<AccountExternalId> byEmailAddress(String email) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE emailAddress >= ? AND emailAddress <= ? ORDER BY emailAddress LIMIT ?")
|
|
||||||
ResultSet<AccountExternalId> suggestByEmailAddress(String emailA,
|
|
||||||
String emailB, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Query
|
@Query
|
||||||
ResultSet<AccountExternalId> all() throws OrmException;
|
ResultSet<AccountExternalId> all() throws OrmException;
|
||||||
}
|
}
|
||||||
|
@@ -21,10 +21,6 @@ ON accounts (full_name);
|
|||||||
CREATE INDEX account_external_ids_byAccount
|
CREATE INDEX account_external_ids_byAccount
|
||||||
ON account_external_ids (account_id);
|
ON account_external_ids (account_id);
|
||||||
|
|
||||||
-- covers: byEmailAddress, suggestByEmailAddress
|
|
||||||
CREATE INDEX account_external_ids_byEmail
|
|
||||||
ON account_external_ids (email_address);
|
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- AccountGroupMemberAccess
|
-- AccountGroupMemberAccess
|
||||||
|
@@ -25,11 +25,6 @@ CREATE INDEX account_external_ids_byAccount
|
|||||||
ON account_external_ids (account_id)
|
ON account_external_ids (account_id)
|
||||||
#
|
#
|
||||||
|
|
||||||
-- covers: byEmailAddress, suggestByEmailAddress
|
|
||||||
CREATE INDEX account_external_ids_byEmail
|
|
||||||
ON account_external_ids (email_address)
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- AccountGroupMemberAccess
|
-- AccountGroupMemberAccess
|
||||||
|
@@ -68,10 +68,6 @@ ON accounts (full_name);
|
|||||||
CREATE INDEX account_external_ids_byAccount
|
CREATE INDEX account_external_ids_byAccount
|
||||||
ON account_external_ids (account_id);
|
ON account_external_ids (account_id);
|
||||||
|
|
||||||
-- covers: byEmailAddress, suggestByEmailAddress
|
|
||||||
CREATE INDEX account_external_ids_byEmail
|
|
||||||
ON account_external_ids (email_address);
|
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- AccountGroupMemberAccess
|
-- AccountGroupMemberAccess
|
||||||
|
@@ -30,11 +30,7 @@ import com.google.gerrit.metrics.Description.Units;
|
|||||||
import com.google.gerrit.metrics.MetricMaker;
|
import com.google.gerrit.metrics.MetricMaker;
|
||||||
import com.google.gerrit.metrics.Timer0;
|
import com.google.gerrit.metrics.Timer0;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
|
||||||
import com.google.gerrit.server.account.AccountControl;
|
|
||||||
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
|
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
|
||||||
import com.google.gerrit.server.account.AccountLoader;
|
import com.google.gerrit.server.account.AccountLoader;
|
||||||
import com.google.gerrit.server.account.AccountState;
|
import com.google.gerrit.server.account.AccountState;
|
||||||
@@ -42,8 +38,6 @@ import com.google.gerrit.server.account.GroupBackend;
|
|||||||
import com.google.gerrit.server.account.GroupMembers;
|
import com.google.gerrit.server.account.GroupMembers;
|
||||||
import com.google.gerrit.server.change.PostReviewers;
|
import com.google.gerrit.server.change.PostReviewers;
|
||||||
import com.google.gerrit.server.change.SuggestReviewers;
|
import com.google.gerrit.server.change.SuggestReviewers;
|
||||||
import com.google.gerrit.server.index.account.AccountIndex;
|
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
@@ -102,47 +96,34 @@ public class ReviewersUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String MAX_SUFFIX = "\u9fa5";
|
|
||||||
// Generate a candidate list at 3x the size of what the user wants to see to
|
// Generate a candidate list at 3x the size of what the user wants to see to
|
||||||
// give the ranking algorithm a good set of candidates it can work with
|
// give the ranking algorithm a good set of candidates it can work with
|
||||||
private static final int CANDIDATE_LIST_MULTIPLIER = 3;
|
private static final int CANDIDATE_LIST_MULTIPLIER = 3;
|
||||||
|
|
||||||
private final AccountCache accountCache;
|
|
||||||
private final AccountControl accountControl;
|
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final AccountLoader accountLoader;
|
private final AccountLoader accountLoader;
|
||||||
private final AccountQueryBuilder accountQueryBuilder;
|
private final AccountQueryBuilder accountQueryBuilder;
|
||||||
private final AccountQueryProcessor accountQueryProcessor;
|
private final AccountQueryProcessor accountQueryProcessor;
|
||||||
private final GroupBackend groupBackend;
|
private final GroupBackend groupBackend;
|
||||||
private final GroupMembers.Factory groupMembersFactory;
|
private final GroupMembers.Factory groupMembersFactory;
|
||||||
private final Provider<CurrentUser> currentUser;
|
private final Provider<CurrentUser> currentUser;
|
||||||
private final Provider<ReviewDb> dbProvider;
|
|
||||||
private final ReviewerRecommender reviewerRecommender;
|
private final ReviewerRecommender reviewerRecommender;
|
||||||
private final Metrics metrics;
|
private final Metrics metrics;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ReviewersUtil(AccountCache accountCache,
|
ReviewersUtil(AccountLoader.Factory accountLoaderFactory,
|
||||||
AccountControl.Factory accountControlFactory,
|
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
AccountLoader.Factory accountLoaderFactory,
|
|
||||||
AccountQueryBuilder accountQueryBuilder,
|
AccountQueryBuilder accountQueryBuilder,
|
||||||
AccountQueryProcessor accountQueryProcessor,
|
AccountQueryProcessor accountQueryProcessor,
|
||||||
GroupBackend groupBackend,
|
GroupBackend groupBackend,
|
||||||
GroupMembers.Factory groupMembersFactory,
|
GroupMembers.Factory groupMembersFactory,
|
||||||
Provider<CurrentUser> currentUser,
|
Provider<CurrentUser> currentUser,
|
||||||
Provider<ReviewDb> dbProvider,
|
|
||||||
ReviewerRecommender reviewerRecommender,
|
ReviewerRecommender reviewerRecommender,
|
||||||
Metrics metrics) {
|
Metrics metrics) {
|
||||||
Set<FillOptions> fillOptions = EnumSet.of(FillOptions.SECONDARY_EMAILS);
|
Set<FillOptions> fillOptions = EnumSet.of(FillOptions.SECONDARY_EMAILS);
|
||||||
fillOptions.addAll(AccountLoader.DETAILED_OPTIONS);
|
fillOptions.addAll(AccountLoader.DETAILED_OPTIONS);
|
||||||
this.accountCache = accountCache;
|
|
||||||
this.accountControl = accountControlFactory.get();
|
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountLoader = accountLoaderFactory.create(fillOptions);
|
this.accountLoader = accountLoaderFactory.create(fillOptions);
|
||||||
this.accountQueryBuilder = accountQueryBuilder;
|
this.accountQueryBuilder = accountQueryBuilder;
|
||||||
this.accountQueryProcessor = accountQueryProcessor;
|
this.accountQueryProcessor = accountQueryProcessor;
|
||||||
this.currentUser = currentUser;
|
this.currentUser = currentUser;
|
||||||
this.dbProvider = dbProvider;
|
|
||||||
this.groupBackend = groupBackend;
|
this.groupBackend = groupBackend;
|
||||||
this.groupMembersFactory = groupMembersFactory;
|
this.groupMembersFactory = groupMembersFactory;
|
||||||
this.reviewerRecommender = reviewerRecommender;
|
this.reviewerRecommender = reviewerRecommender;
|
||||||
@@ -189,20 +170,8 @@ public class ReviewersUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<Account.Id> suggestAccounts(SuggestReviewers suggestReviewers,
|
private List<Account.Id> suggestAccounts(SuggestReviewers suggestReviewers,
|
||||||
VisibilityControl visibilityControl)
|
VisibilityControl visibilityControl) throws OrmException {
|
||||||
throws OrmException {
|
|
||||||
try (Timer0.Context ctx = metrics.queryAccountsLatency.start()) {
|
try (Timer0.Context ctx = metrics.queryAccountsLatency.start()) {
|
||||||
AccountIndex searchIndex = accountIndexes.getSearchIndex();
|
|
||||||
if (searchIndex != null) {
|
|
||||||
return suggestAccountsFromIndex(suggestReviewers, visibilityControl);
|
|
||||||
}
|
|
||||||
return suggestAccountsFromDb(suggestReviewers, visibilityControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Account.Id> suggestAccountsFromIndex(
|
|
||||||
SuggestReviewers suggestReviewers, VisibilityControl visibilityControl)
|
|
||||||
throws OrmException {
|
|
||||||
try {
|
try {
|
||||||
Set<Account.Id> matches = new HashSet<>();
|
Set<Account.Id> matches = new HashSet<>();
|
||||||
QueryResult<AccountState> result = accountQueryProcessor
|
QueryResult<AccountState> result = accountQueryProcessor
|
||||||
@@ -219,60 +188,6 @@ public class ReviewersUtil {
|
|||||||
return ImmutableList.of();
|
return ImmutableList.of();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Account.Id> suggestAccountsFromDb(
|
|
||||||
SuggestReviewers suggestReviewers, VisibilityControl visibilityControl)
|
|
||||||
throws OrmException {
|
|
||||||
String query = suggestReviewers.getQuery();
|
|
||||||
int limit = suggestReviewers.getLimit() * CANDIDATE_LIST_MULTIPLIER;
|
|
||||||
|
|
||||||
String a = query;
|
|
||||||
String b = a + MAX_SUFFIX;
|
|
||||||
|
|
||||||
Set<Account.Id> r = new HashSet<>();
|
|
||||||
|
|
||||||
for (Account p : dbProvider.get().accounts()
|
|
||||||
.suggestByFullName(a, b, limit)) {
|
|
||||||
if (p.isActive()) {
|
|
||||||
addSuggestion(r, p.getId(), visibilityControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.size() < limit) {
|
|
||||||
for (Account p : dbProvider.get().accounts()
|
|
||||||
.suggestByPreferredEmail(a, b, limit - r.size())) {
|
|
||||||
if (p.isActive()) {
|
|
||||||
addSuggestion(r, p.getId(), visibilityControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r.size() < limit) {
|
|
||||||
for (AccountExternalId e : dbProvider.get().accountExternalIds()
|
|
||||||
.suggestByEmailAddress(a, b, limit - r.size())) {
|
|
||||||
if (!r.contains(e.getAccountId())) {
|
|
||||||
Account p = accountCache.get(e.getAccountId()).getAccount();
|
|
||||||
if (p.isActive()) {
|
|
||||||
addSuggestion(r, p.getId(), visibilityControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ArrayList<>(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addSuggestion(Set<Account.Id> map,
|
|
||||||
Account.Id account, VisibilityControl visibilityControl)
|
|
||||||
throws OrmException {
|
|
||||||
if (!map.contains(account)
|
|
||||||
// Can the suggestion see the change?
|
|
||||||
&& visibilityControl.isVisibleTo(account)
|
|
||||||
// Can the current user see the account?
|
|
||||||
&& accountControl.canSee(account)) {
|
|
||||||
map.add(account);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Account.Id> recommendAccounts(ChangeNotes changeNotes,
|
private List<Account.Id> recommendAccounts(ChangeNotes changeNotes,
|
||||||
|
@@ -21,7 +21,6 @@ import com.google.gerrit.reviewdb.client.Account;
|
|||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.cache.CacheModule;
|
import com.google.gerrit.server.cache.CacheModule;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
import com.google.gwtorm.server.SchemaFactory;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -87,15 +86,12 @@ public class AccountByEmailCacheImpl implements AccountByEmailCache {
|
|||||||
|
|
||||||
static class Loader extends CacheLoader<String, Set<Account.Id>> {
|
static class Loader extends CacheLoader<String, Set<Account.Id>> {
|
||||||
private final SchemaFactory<ReviewDb> schema;
|
private final SchemaFactory<ReviewDb> schema;
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Loader(SchemaFactory<ReviewDb> schema,
|
Loader(SchemaFactory<ReviewDb> schema,
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
Provider<InternalAccountQuery> accountQueryProvider) {
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,19 +102,12 @@ public class AccountByEmailCacheImpl implements AccountByEmailCache {
|
|||||||
for (Account a : db.accounts().byPreferredEmail(email)) {
|
for (Account a : db.accounts().byPreferredEmail(email)) {
|
||||||
r.add(a.getId());
|
r.add(a.getId());
|
||||||
}
|
}
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
for (AccountState accountState : accountQueryProvider.get()
|
for (AccountState accountState : accountQueryProvider.get()
|
||||||
.byExternalId(
|
.byExternalId(
|
||||||
(new AccountExternalId.Key(AccountExternalId.SCHEME_MAILTO,
|
(new AccountExternalId.Key(AccountExternalId.SCHEME_MAILTO,
|
||||||
email)).get())) {
|
email)).get())) {
|
||||||
r.add(accountState.getAccount().getId());
|
r.add(accountState.getAccount().getId());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (AccountExternalId a : db.accountExternalIds()
|
|
||||||
.byEmailAddress(email)) {
|
|
||||||
r.add(a.getAccountId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ImmutableSet.copyOf(r);
|
return ImmutableSet.copyOf(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,6 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
|
|||||||
import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
|
import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
|
||||||
import com.google.gerrit.server.cache.CacheModule;
|
import com.google.gerrit.server.cache.CacheModule;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.index.account.AccountIndexer;
|
import com.google.gerrit.server.index.account.AccountIndexer;
|
||||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@@ -231,16 +230,10 @@ public class AccountCacheImpl implements AccountCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class ByNameLoader extends CacheLoader<String, Optional<Account.Id>> {
|
static class ByNameLoader extends CacheLoader<String, Optional<Account.Id>> {
|
||||||
private final SchemaFactory<ReviewDb> schema;
|
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ByNameLoader(SchemaFactory<ReviewDb> sf,
|
ByNameLoader(Provider<InternalAccountQuery> accountQueryProvider) {
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
|
||||||
this.schema = sf;
|
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,17 +242,10 @@ public class AccountCacheImpl implements AccountCache {
|
|||||||
AccountExternalId.Key key = new AccountExternalId.Key( //
|
AccountExternalId.Key key = new AccountExternalId.Key( //
|
||||||
AccountExternalId.SCHEME_USERNAME, //
|
AccountExternalId.SCHEME_USERNAME, //
|
||||||
username);
|
username);
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
AccountState accountState =
|
AccountState accountState =
|
||||||
accountQueryProvider.get().oneByExternalId(key.get());
|
accountQueryProvider.get().oneByExternalId(key.get());
|
||||||
return Optional.ofNullable(accountState)
|
return Optional.ofNullable(accountState)
|
||||||
.map(s -> s.getAccount().getId());
|
.map(s -> s.getAccount().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
try (ReviewDb db = schema.open()) {
|
|
||||||
return Optional.ofNullable(db.accountExternalIds().get(key))
|
|
||||||
.map(AccountExternalId::getAccountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,6 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
|
|||||||
import com.google.gerrit.reviewdb.client.AccountGroupMember;
|
import com.google.gerrit.reviewdb.client.AccountGroupMember;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.project.ProjectCache;
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
@@ -63,7 +62,6 @@ public class AccountManager {
|
|||||||
private final ProjectCache projectCache;
|
private final ProjectCache projectCache;
|
||||||
private final AtomicBoolean awaitsFirstAccountCheck;
|
private final AtomicBoolean awaitsFirstAccountCheck;
|
||||||
private final AuditService auditService;
|
private final AuditService auditService;
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -75,7 +73,6 @@ public class AccountManager {
|
|||||||
ChangeUserName.Factory changeUserNameFactory,
|
ChangeUserName.Factory changeUserNameFactory,
|
||||||
ProjectCache projectCache,
|
ProjectCache projectCache,
|
||||||
AuditService auditService,
|
AuditService auditService,
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
Provider<InternalAccountQuery> accountQueryProvider) {
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
this.byIdCache = byIdCache;
|
this.byIdCache = byIdCache;
|
||||||
@@ -86,7 +83,6 @@ public class AccountManager {
|
|||||||
this.projectCache = projectCache;
|
this.projectCache = projectCache;
|
||||||
this.awaitsFirstAccountCheck = new AtomicBoolean(true);
|
this.awaitsFirstAccountCheck = new AtomicBoolean(true);
|
||||||
this.auditService = auditService;
|
this.auditService = auditService;
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,21 +92,11 @@ public class AccountManager {
|
|||||||
public Optional<Account.Id> lookup(String externalId)
|
public Optional<Account.Id> lookup(String externalId)
|
||||||
throws AccountException {
|
throws AccountException {
|
||||||
try {
|
try {
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
AccountState accountState =
|
AccountState accountState =
|
||||||
accountQueryProvider.get().oneByExternalId(externalId);
|
accountQueryProvider.get().oneByExternalId(externalId);
|
||||||
return accountState != null
|
return accountState != null
|
||||||
? Optional.of(accountState.getAccount().getId())
|
? Optional.of(accountState.getAccount().getId())
|
||||||
: Optional.empty();
|
: Optional.empty();
|
||||||
}
|
|
||||||
|
|
||||||
try (ReviewDb db = schema.open()) {
|
|
||||||
AccountExternalId ext =
|
|
||||||
db.accountExternalIds().get(new AccountExternalId.Key(externalId));
|
|
||||||
return ext != null
|
|
||||||
? Optional.of(ext.getAccountId())
|
|
||||||
: Optional.empty();
|
|
||||||
}
|
|
||||||
} catch (OrmException e) {
|
} catch (OrmException e) {
|
||||||
throw new AccountException("Cannot lookup account " + externalId, e);
|
throw new AccountException("Cannot lookup account " + externalId, e);
|
||||||
}
|
}
|
||||||
@@ -130,7 +116,7 @@ public class AccountManager {
|
|||||||
try {
|
try {
|
||||||
try (ReviewDb db = schema.open()) {
|
try (ReviewDb db = schema.open()) {
|
||||||
AccountExternalId.Key key = id(who);
|
AccountExternalId.Key key = id(who);
|
||||||
AccountExternalId id = getAccountExternalId(db, key);
|
AccountExternalId id = getAccountExternalId(key);
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
// New account, automatically create and return.
|
// New account, automatically create and return.
|
||||||
//
|
//
|
||||||
@@ -152,9 +138,8 @@ public class AccountManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccountExternalId getAccountExternalId(ReviewDb db,
|
private AccountExternalId getAccountExternalId(AccountExternalId.Key key)
|
||||||
AccountExternalId.Key key) throws OrmException {
|
throws OrmException {
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
AccountState accountState =
|
AccountState accountState =
|
||||||
accountQueryProvider.get().oneByExternalId(key.get());
|
accountQueryProvider.get().oneByExternalId(key.get());
|
||||||
if (accountState != null) {
|
if (accountState != null) {
|
||||||
@@ -167,24 +152,6 @@ public class AccountManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have at the moment an account_by_external_id cache
|
|
||||||
// but by using the accounts cache we get the list of external_ids
|
|
||||||
// without having to query the DB every time
|
|
||||||
if (key.getScheme().equals(AccountExternalId.SCHEME_GERRIT)
|
|
||||||
|| key.getScheme().equals(AccountExternalId.SCHEME_USERNAME)) {
|
|
||||||
AccountState state = byIdCache.getByUsername(
|
|
||||||
key.get().substring(key.getScheme().length()));
|
|
||||||
if (state != null) {
|
|
||||||
for (AccountExternalId accountExternalId : state.getExternalIds()) {
|
|
||||||
if (accountExternalId.getKey().equals(key)) {
|
|
||||||
return accountExternalId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return db.accountExternalIds().get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update(ReviewDb db, AuthRequest who, AccountExternalId extId)
|
private void update(ReviewDb db, AuthRequest who, AccountExternalId extId)
|
||||||
throws OrmException, IOException {
|
throws OrmException, IOException {
|
||||||
IdentifiedUser user = userFactory.create(extId.getAccountId());
|
IdentifiedUser user = userFactory.create(extId.getAccountId());
|
||||||
@@ -390,7 +357,7 @@ public class AccountManager {
|
|||||||
throws AccountException, OrmException, IOException {
|
throws AccountException, OrmException, IOException {
|
||||||
try (ReviewDb db = schema.open()) {
|
try (ReviewDb db = schema.open()) {
|
||||||
AccountExternalId.Key key = id(who);
|
AccountExternalId.Key key = id(who);
|
||||||
AccountExternalId extId = getAccountExternalId(db, key);
|
AccountExternalId extId = getAccountExternalId(key);
|
||||||
if (extId != null) {
|
if (extId != null) {
|
||||||
if (!extId.getAccountId().equals(to)) {
|
if (!extId.getAccountId().equals(to)) {
|
||||||
throw new AccountException("Identity in use by another account");
|
throw new AccountException("Identity in use by another account");
|
||||||
@@ -474,7 +441,7 @@ public class AccountManager {
|
|||||||
throws AccountException, OrmException, IOException {
|
throws AccountException, OrmException, IOException {
|
||||||
try (ReviewDb db = schema.open()) {
|
try (ReviewDb db = schema.open()) {
|
||||||
AccountExternalId.Key key = id(who);
|
AccountExternalId.Key key = id(who);
|
||||||
AccountExternalId extId = getAccountExternalId(db, key);
|
AccountExternalId extId = getAccountExternalId(key);
|
||||||
if (extId != null) {
|
if (extId != null) {
|
||||||
if (!extId.getAccountId().equals(from)) {
|
if (!extId.getAccountId().equals(from)) {
|
||||||
throw new AccountException(
|
throw new AccountException(
|
||||||
|
@@ -17,9 +17,7 @@ package com.google.gerrit.server.account;
|
|||||||
import static java.util.stream.Collectors.toSet;
|
import static java.util.stream.Collectors.toSet;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -38,19 +36,16 @@ public class AccountResolver {
|
|||||||
private final Realm realm;
|
private final Realm realm;
|
||||||
private final AccountByEmailCache byEmail;
|
private final AccountByEmailCache byEmail;
|
||||||
private final AccountCache byId;
|
private final AccountCache byId;
|
||||||
private final AccountIndexCollection accountIndexes;
|
|
||||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AccountResolver(Realm realm,
|
AccountResolver(Realm realm,
|
||||||
AccountByEmailCache byEmail,
|
AccountByEmailCache byEmail,
|
||||||
AccountCache byId,
|
AccountCache byId,
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
Provider<InternalAccountQuery> accountQueryProvider) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.byEmail = byEmail;
|
this.byEmail = byEmail;
|
||||||
this.byId = byId;
|
this.byId = byId;
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +178,6 @@ public class AccountResolver {
|
|||||||
return Collections.singleton(id);
|
return Collections.singleton(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accountIndexes.getSearchIndex() != null) {
|
|
||||||
List<AccountState> m = accountQueryProvider.get().byFullName(nameOrEmail);
|
List<AccountState> m = accountQueryProvider.get().byFullName(nameOrEmail);
|
||||||
if (m.size() == 1) {
|
if (m.size() == 1) {
|
||||||
return Collections.singleton(m.get(0).getAccount().getId());
|
return Collections.singleton(m.get(0).getAccount().getId());
|
||||||
@@ -195,30 +189,4 @@ public class AccountResolver {
|
|||||||
.map(a -> a.getAccount().getId())
|
.map(a -> a.getAccount().getId())
|
||||||
.collect(toSet());
|
.collect(toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Account> m = db.accounts().byFullName(nameOrEmail).toList();
|
|
||||||
if (m.size() == 1) {
|
|
||||||
return Collections.singleton(m.get(0).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point we have no clue. Just perform a whole bunch of suggestions
|
|
||||||
// and pray we come up with a reasonable result list.
|
|
||||||
Set<Account.Id> result = new HashSet<>();
|
|
||||||
String a = nameOrEmail;
|
|
||||||
String b = nameOrEmail + "\u9fa5";
|
|
||||||
for (Account act : db.accounts().suggestByFullName(a, b, 10)) {
|
|
||||||
result.add(act.getId());
|
|
||||||
}
|
|
||||||
for (AccountExternalId extId : db.accountExternalIds()
|
|
||||||
.suggestByKey(
|
|
||||||
new AccountExternalId.Key(AccountExternalId.SCHEME_USERNAME, a),
|
|
||||||
new AccountExternalId.Key(AccountExternalId.SCHEME_USERNAME, b), 10)) {
|
|
||||||
result.add(extId.getAccountId());
|
|
||||||
}
|
|
||||||
for (AccountExternalId extId : db.accountExternalIds()
|
|
||||||
.suggestByEmailAddress(a, b, 10)) {
|
|
||||||
result.add(extId.getAccountId());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -23,13 +23,9 @@ import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
|
|||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
|
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
|
||||||
import com.google.gerrit.server.api.accounts.AccountInfoComparator;
|
import com.google.gerrit.server.api.accounts.AccountInfoComparator;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.index.account.AccountIndex;
|
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gerrit.server.query.QueryParseException;
|
import com.google.gerrit.server.query.QueryParseException;
|
||||||
import com.google.gerrit.server.query.QueryResult;
|
import com.google.gerrit.server.query.QueryResult;
|
||||||
@@ -43,7 +39,6 @@ import org.kohsuke.args4j.Option;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -51,15 +46,10 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class QueryAccounts implements RestReadView<TopLevelResource> {
|
public class QueryAccounts implements RestReadView<TopLevelResource> {
|
||||||
private static final int MAX_SUGGEST_RESULTS = 100;
|
private static final int MAX_SUGGEST_RESULTS = 100;
|
||||||
private static final String MAX_SUFFIX = "\u9fa5";
|
|
||||||
|
|
||||||
private final AccountControl accountControl;
|
|
||||||
private final AccountLoader.Factory accountLoaderFactory;
|
private final AccountLoader.Factory accountLoaderFactory;
|
||||||
private final AccountCache accountCache;
|
|
||||||
private final AccountIndexCollection indexes;
|
|
||||||
private final AccountQueryBuilder queryBuilder;
|
private final AccountQueryBuilder queryBuilder;
|
||||||
private final AccountQueryProcessor queryProcessor;
|
private final AccountQueryProcessor queryProcessor;
|
||||||
private final ReviewDb db;
|
|
||||||
private final boolean suggestConfig;
|
private final boolean suggestConfig;
|
||||||
private final int suggestFrom;
|
private final int suggestFrom;
|
||||||
|
|
||||||
@@ -110,21 +100,13 @@ public class QueryAccounts implements RestReadView<TopLevelResource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
QueryAccounts(AccountControl.Factory accountControlFactory,
|
QueryAccounts(AccountLoader.Factory accountLoaderFactory,
|
||||||
AccountLoader.Factory accountLoaderFactory,
|
|
||||||
AccountCache accountCache,
|
|
||||||
AccountIndexCollection indexes,
|
|
||||||
AccountQueryBuilder queryBuilder,
|
AccountQueryBuilder queryBuilder,
|
||||||
AccountQueryProcessor queryProcessor,
|
AccountQueryProcessor queryProcessor,
|
||||||
ReviewDb db,
|
|
||||||
@GerritServerConfig Config cfg) {
|
@GerritServerConfig Config cfg) {
|
||||||
this.accountControl = accountControlFactory.get();
|
|
||||||
this.accountLoaderFactory = accountLoaderFactory;
|
this.accountLoaderFactory = accountLoaderFactory;
|
||||||
this.accountCache = accountCache;
|
|
||||||
this.indexes = indexes;
|
|
||||||
this.queryBuilder = queryBuilder;
|
this.queryBuilder = queryBuilder;
|
||||||
this.queryProcessor = queryProcessor;
|
this.queryProcessor = queryProcessor;
|
||||||
this.db = db;
|
|
||||||
this.suggestFrom = cfg.getInt("suggest", null, "from", 0);
|
this.suggestFrom = cfg.getInt("suggest", null, "from", 0);
|
||||||
this.options = EnumSet.noneOf(ListAccountsOption.class);
|
this.options = EnumSet.noneOf(ListAccountsOption.class);
|
||||||
|
|
||||||
@@ -169,22 +151,6 @@ public class QueryAccounts implements RestReadView<TopLevelResource> {
|
|||||||
}
|
}
|
||||||
accountLoader = accountLoaderFactory.create(fillOptions);
|
accountLoader = accountLoaderFactory.create(fillOptions);
|
||||||
|
|
||||||
AccountIndex searchIndex = indexes.getSearchIndex();
|
|
||||||
if (searchIndex != null) {
|
|
||||||
return queryFromIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!suggest) {
|
|
||||||
throw new MethodNotAllowedException();
|
|
||||||
}
|
|
||||||
if (start != null) {
|
|
||||||
throw new MethodNotAllowedException("option start not allowed");
|
|
||||||
}
|
|
||||||
return queryFromDb();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<AccountInfo> queryFromIndex()
|
|
||||||
throws BadRequestException, MethodNotAllowedException, OrmException {
|
|
||||||
if (queryProcessor.isDisabled()) {
|
if (queryProcessor.isDisabled()) {
|
||||||
throw new MethodNotAllowedException("query disabled");
|
throw new MethodNotAllowedException("query disabled");
|
||||||
}
|
}
|
||||||
@@ -223,57 +189,4 @@ public class QueryAccounts implements RestReadView<TopLevelResource> {
|
|||||||
throw new BadRequestException(e.getMessage());
|
throw new BadRequestException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AccountInfo> queryFromDb() throws OrmException {
|
|
||||||
String a = query;
|
|
||||||
String b = a + MAX_SUFFIX;
|
|
||||||
|
|
||||||
Map<Account.Id, AccountInfo> matches = new LinkedHashMap<>();
|
|
||||||
Map<Account.Id, String> queryEmail = new HashMap<>();
|
|
||||||
|
|
||||||
for (Account p : db.accounts().suggestByFullName(a, b, suggestLimit)) {
|
|
||||||
addSuggestion(matches, p);
|
|
||||||
}
|
|
||||||
if (matches.size() < suggestLimit) {
|
|
||||||
for (Account p : db.accounts()
|
|
||||||
.suggestByPreferredEmail(a, b, suggestLimit - matches.size())) {
|
|
||||||
addSuggestion(matches, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (matches.size() < suggestLimit) {
|
|
||||||
for (AccountExternalId e : db.accountExternalIds()
|
|
||||||
.suggestByEmailAddress(a, b, suggestLimit - matches.size())) {
|
|
||||||
if (addSuggestion(matches, e.getAccountId())) {
|
|
||||||
queryEmail.put(e.getAccountId(), e.getEmailAddress());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
accountLoader.fill();
|
|
||||||
for (Map.Entry<Account.Id, String> p : queryEmail.entrySet()) {
|
|
||||||
AccountInfo info = matches.get(p.getKey());
|
|
||||||
if (info != null) {
|
|
||||||
info.email = p.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return AccountInfoComparator.ORDER_NULLS_LAST.sortedCopy(matches.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addSuggestion(Map<Account.Id, AccountInfo> map, Account a) {
|
|
||||||
if (!a.isActive()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Account.Id id = a.getId();
|
|
||||||
if (!map.containsKey(id) && accountControl.canSee(id)) {
|
|
||||||
map.put(id, accountLoader.get(id));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addSuggestion(Map<Account.Id, AccountInfo> map, Account.Id id) {
|
|
||||||
Account a = accountCache.get(id).getAccount();
|
|
||||||
return addSuggestion(map, a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,6 @@ import com.google.gerrit.server.config.AnonymousCowardName;
|
|||||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
|
||||||
import com.google.gerrit.server.mail.EmailSettings;
|
import com.google.gerrit.server.mail.EmailSettings;
|
||||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||||
import com.google.gerrit.server.patch.PatchListCache;
|
import com.google.gerrit.server.patch.PatchListCache;
|
||||||
@@ -82,7 +81,6 @@ public class EmailArguments {
|
|||||||
final EmailSettings settings;
|
final EmailSettings settings;
|
||||||
final DynamicSet<OutgoingEmailValidationListener> outgoingEmailValidationListeners;
|
final DynamicSet<OutgoingEmailValidationListener> outgoingEmailValidationListeners;
|
||||||
final StarredChangesUtil starredChangesUtil;
|
final StarredChangesUtil starredChangesUtil;
|
||||||
final AccountIndexCollection accountIndexes;
|
|
||||||
final Provider<InternalAccountQuery> accountQueryProvider;
|
final Provider<InternalAccountQuery> accountQueryProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -111,7 +109,6 @@ public class EmailArguments {
|
|||||||
SitePaths site,
|
SitePaths site,
|
||||||
DynamicSet<OutgoingEmailValidationListener> outgoingEmailValidationListeners,
|
DynamicSet<OutgoingEmailValidationListener> outgoingEmailValidationListeners,
|
||||||
StarredChangesUtil starredChangesUtil,
|
StarredChangesUtil starredChangesUtil,
|
||||||
AccountIndexCollection accountIndexes,
|
|
||||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
Provider<InternalAccountQuery> accountQueryProvider) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.projectCache = projectCache;
|
this.projectCache = projectCache;
|
||||||
@@ -141,7 +138,6 @@ public class EmailArguments {
|
|||||||
this.site = site;
|
this.site = site;
|
||||||
this.outgoingEmailValidationListeners = outgoingEmailValidationListeners;
|
this.outgoingEmailValidationListeners = outgoingEmailValidationListeners;
|
||||||
this.starredChangesUtil = starredChangesUtil;
|
this.starredChangesUtil = starredChangesUtil;
|
||||||
this.accountIndexes = accountIndexes;
|
|
||||||
this.accountQueryProvider = accountQueryProvider;
|
this.accountQueryProvider = accountQueryProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,6 @@ import com.google.gerrit.common.data.GroupReference;
|
|||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroupMember;
|
import com.google.gerrit.reviewdb.client.AccountGroupMember;
|
||||||
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
|
|
||||||
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
|
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
@@ -66,32 +65,6 @@ public class ProjectWatch {
|
|||||||
|
|
||||||
/** Returns all watchers that are relevant */
|
/** Returns all watchers that are relevant */
|
||||||
public final Watchers getWatchers(NotifyType type) throws OrmException {
|
public final Watchers getWatchers(NotifyType type) throws OrmException {
|
||||||
Watchers matching;
|
|
||||||
if (args.accountIndexes.getSearchIndex() != null) {
|
|
||||||
matching = getWatchersFromIndex(type);
|
|
||||||
} else {
|
|
||||||
matching = getWatchersFromDb(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ProjectState state : projectState.tree()) {
|
|
||||||
for (NotifyConfig nc : state.getConfig().getNotifyConfigs()) {
|
|
||||||
if (nc.isNotify(type)) {
|
|
||||||
try {
|
|
||||||
add(matching, nc);
|
|
||||||
} catch (QueryParseException e) {
|
|
||||||
log.warn("Project {} has invalid notify {} filter \"{}\": {}",
|
|
||||||
state.getProject().getName(), nc.getName(),
|
|
||||||
nc.getFilter(), e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matching;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Watchers getWatchersFromIndex(NotifyType type)
|
|
||||||
throws OrmException {
|
|
||||||
Watchers matching = new Watchers();
|
Watchers matching = new Watchers();
|
||||||
Set<Account.Id> projectWatchers = new HashSet<>();
|
Set<Account.Id> projectWatchers = new HashSet<>();
|
||||||
|
|
||||||
@@ -120,28 +93,21 @@ public class ProjectWatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matching;
|
|
||||||
|
for (ProjectState state : projectState.tree()) {
|
||||||
|
for (NotifyConfig nc : state.getConfig().getNotifyConfigs()) {
|
||||||
|
if (nc.isNotify(type)) {
|
||||||
|
try {
|
||||||
|
add(matching, nc);
|
||||||
|
} catch (QueryParseException e) {
|
||||||
|
log.warn("Project {} has invalid notify {} filter \"{}\": {}",
|
||||||
|
state.getProject().getName(), nc.getName(),
|
||||||
|
nc.getFilter(), e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Watchers getWatchersFromDb(NotifyType type)
|
|
||||||
throws OrmException {
|
|
||||||
Watchers matching = new Watchers();
|
|
||||||
Set<Account.Id> projectWatchers = new HashSet<>();
|
|
||||||
|
|
||||||
for (AccountProjectWatch w : args.db.get().accountProjectWatches()
|
|
||||||
.byProject(project)) {
|
|
||||||
if (add(matching, w, type)) {
|
|
||||||
// We only want to prevent matching All-Projects if this filter hits
|
|
||||||
projectWatchers.add(w.getAccountId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AccountProjectWatch w : args.db.get().accountProjectWatches()
|
|
||||||
.byProject(args.allProjectsName)) {
|
|
||||||
if (!projectWatchers.contains(w.getAccountId())) {
|
|
||||||
add(matching, w, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matching;
|
return matching;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,25 +206,6 @@ public class ProjectWatch {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean add(Watchers matching, AccountProjectWatch w, NotifyType type)
|
|
||||||
throws OrmException {
|
|
||||||
IdentifiedUser user = args.identifiedUserFactory.create(w.getAccountId());
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (filterMatch(user, w.getFilter())) {
|
|
||||||
// If we are set to notify on this type, add the user.
|
|
||||||
// Otherwise, still return true to stop notifications for this user.
|
|
||||||
if (w.isNotify(type)) {
|
|
||||||
matching.bcc.accounts.add(w.getAccountId());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (QueryParseException e) {
|
|
||||||
// Ignore broken filter expressions.
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean filterMatch(CurrentUser user, String filter)
|
private boolean filterMatch(CurrentUser user, String filter)
|
||||||
throws OrmException, QueryParseException {
|
throws OrmException, QueryParseException {
|
||||||
ChangeQueryBuilder qb;
|
ChangeQueryBuilder qb;
|
||||||
|
Submodule plugins/singleusergroup updated: 7a9b8781cf...d0d51ea46e
Reference in New Issue
Block a user