Use account index to check if GPG key is used by another account
When posting a new GPG key use the account index to check if the GPG key is already associated with another account. This is a preparation for moving the external IDs (GPG keys) from ReviewDb into git. If an account index is not available we still fall back to check the existence of the key in the database. Change-Id: I00d0930ce9c92c7caac19311b1092f882c4b20e0 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -39,6 +39,7 @@ import com.google.gerrit.gpg.GerritPublicKeyChecker;
|
||||
import com.google.gerrit.gpg.PublicKeyChecker;
|
||||
import com.google.gerrit.gpg.PublicKeyStore;
|
||||
import com.google.gerrit.gpg.server.PostGpgKeys.Input;
|
||||
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.CurrentUser;
|
||||
@@ -46,7 +47,10 @@ import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.account.AccountCache;
|
||||
import com.google.gerrit.server.account.AccountResource;
|
||||
import com.google.gerrit.server.account.AccountState;
|
||||
import com.google.gerrit.server.index.account.AccountIndexCollection;
|
||||
import com.google.gerrit.server.mail.AddKeySender;
|
||||
import com.google.gerrit.server.query.account.InternalAccountQuery;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
@@ -87,6 +91,8 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||
private final GerritPublicKeyChecker.Factory checkerFactory;
|
||||
private final AddKeySender.Factory addKeyFactory;
|
||||
private final AccountCache accountCache;
|
||||
private final AccountIndexCollection accountIndexes;
|
||||
private final Provider<InternalAccountQuery> accountQueryProvider;
|
||||
|
||||
@Inject
|
||||
PostGpgKeys(@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
||||
@@ -95,7 +101,9 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||
Provider<PublicKeyStore> storeProvider,
|
||||
GerritPublicKeyChecker.Factory checkerFactory,
|
||||
AddKeySender.Factory addKeyFactory,
|
||||
AccountCache accountCache) {
|
||||
AccountCache accountCache,
|
||||
AccountIndexCollection accountIndexes,
|
||||
Provider<InternalAccountQuery> accountQueryProvider) {
|
||||
this.serverIdent = serverIdent;
|
||||
this.db = db;
|
||||
this.self = self;
|
||||
@@ -103,6 +111,8 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||
this.checkerFactory = checkerFactory;
|
||||
this.addKeyFactory = addKeyFactory;
|
||||
this.accountCache = accountCache;
|
||||
this.accountIndexes = accountIndexes;
|
||||
this.accountQueryProvider = accountQueryProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,15 +132,28 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||
for (PGPPublicKeyRing keyRing : newKeys) {
|
||||
PGPPublicKey key = keyRing.getPublicKey();
|
||||
AccountExternalId.Key extIdKey = toExtIdKey(key.getFingerprint());
|
||||
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");
|
||||
if (accountIndexes.getSearchIndex() != null) {
|
||||
Account account = getAccountByExternalId(extIdKey.get());
|
||||
if (account != null) {
|
||||
if (!account.getId().equals(rsrc.getUser().getAccountId())) {
|
||||
throw new ResourceConflictException(
|
||||
"GPG key already associated with another account");
|
||||
}
|
||||
} else {
|
||||
newExtIds.add(
|
||||
new AccountExternalId(rsrc.getUser().getAccountId(), extIdKey));
|
||||
}
|
||||
} else {
|
||||
newExtIds.add(
|
||||
new AccountExternalId(rsrc.getUser().getAccountId(), extIdKey));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +280,33 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||
BaseEncoding.base16().encode(fp));
|
||||
}
|
||||
|
||||
private Account getAccountByExternalId(String externalId)
|
||||
throws OrmException {
|
||||
List<AccountState> accountStates =
|
||||
accountQueryProvider.get().byExternalId(externalId);
|
||||
|
||||
if (accountStates.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (accountStates.size() > 1) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("GPG key ").append(externalId)
|
||||
.append(" associated with multiple accounts: ");
|
||||
Joiner.on(", ").appendTo(msg,
|
||||
Lists.transform(accountStates, new Function<AccountState, String>() {
|
||||
@Override
|
||||
public String apply(AccountState accountState) {
|
||||
return accountState.getAccount().getId().toString();
|
||||
}
|
||||
}));
|
||||
log.error(msg.toString());
|
||||
throw new IllegalStateException(msg.toString());
|
||||
}
|
||||
|
||||
return accountStates.get(0).getAccount();
|
||||
}
|
||||
|
||||
private Map<String, GpgKeyInfo> toJson(
|
||||
Collection<PGPPublicKeyRing> keys,
|
||||
Set<Fingerprint> deleted, PublicKeyStore store, IdentifiedUser user)
|
||||
|
||||
Reference in New Issue
Block a user