Fix the missing DB entry in Gerrit DB
Due to an unknown reason (still under investigation), a few of the new LDAP users were not able to login after first time because the Gerrit DB was missing one of the two entries needed to authenticate the user (the second entry is only needed for the users with non-null usernames). The entry with external Id - "gerrit:abc" was never inserted to DB in such cases whereas the entry with external id - "username:abc" was created resulting in an account creation for the user. This causes inconsistency in the DB. An account gets created in first login attempt and second attempt fails to create missing external id because the "username:abc" entry already exists causing the DB action to rollback. As this bug is very infrequent and hard to replicate, this change provides an after-fix for the issue i.e. fixes the problem when an entry is missing in Gerrit DB. It checks if there exists an account already for the given username and links the newly created external ID to that account. It prevents the need to manually enter the missing entries in DB to solve the issue. Bug: Issue 7652 Change-Id: Icd2fbf77971f00783277f88fa085ea1bc761878f
This commit is contained in:
parent
e0072fdd7a
commit
fcc90699fd
|
@ -14,6 +14,7 @@
|
|||
|
||||
package com.google.gerrit.server.account;
|
||||
|
||||
import static com.google.gerrit.server.account.ExternalId.SCHEME_USERNAME;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
@ -107,8 +108,22 @@ public class AccountManager {
|
|||
try (ReviewDb db = schema.open()) {
|
||||
ExternalId id = findExternalId(db, who.getExternalIdKey());
|
||||
if (id == null) {
|
||||
if (who.getUserName() != null) {
|
||||
ExternalId.Key key = ExternalId.Key.create(SCHEME_USERNAME, who.getUserName());
|
||||
ExternalId existingId = findExternalId(db, key);
|
||||
if (existingId != null) {
|
||||
// An inconsistency is detected in the database, having a record for scheme "username:"
|
||||
// but no record for scheme "gerrit:". Try to recover by linking
|
||||
// "gerrit:" identity to the existing account.
|
||||
log.warn(
|
||||
"User {} already has an account; link new identity to the existing account.",
|
||||
who.getUserName());
|
||||
return link(existingId.accountId(), who);
|
||||
}
|
||||
}
|
||||
// New account, automatically create and return.
|
||||
//
|
||||
log.info("External ID not found. Attempting to create new account.");
|
||||
return create(db, who);
|
||||
}
|
||||
|
||||
|
@ -348,13 +363,16 @@ public class AccountManager {
|
|||
public AuthResult link(Account.Id to, AuthRequest who)
|
||||
throws AccountException, OrmException, IOException {
|
||||
try (ReviewDb db = schema.open()) {
|
||||
log.info("Link another authentication identity to an existing account");
|
||||
ExternalId extId = findExternalId(db, who.getExternalIdKey());
|
||||
if (extId != null) {
|
||||
if (!extId.accountId().equals(to)) {
|
||||
throw new AccountException("Identity in use by another account");
|
||||
}
|
||||
log.info("Updating existing external ID data");
|
||||
update(db, who, extId);
|
||||
} else {
|
||||
log.info("Linking new external ID to the existing account");
|
||||
externalIdsUpdateFactory
|
||||
.create()
|
||||
.insert(
|
||||
|
|
Loading…
Reference in New Issue