Migrate external IDs to NoteDb (part 3)
This is the third part of migrating external IDs from ReviewDb to NoteDb. This change: * changes the code to always read external IDs from NoteDb (the user.readExternalIdsFromGit configuration parameter is removed) * bumps the database schema version * deletes the database table for external IDs Pushing to the refs/meta/external-ids branch is still prevented by a commit validator. Since all external IDs are now in NoteDb only we could allow pushing to refs/meta/external-ids. However we would still like to do validation of the branch content and reject invalid content (e.g. invalid Git config files, usage of non-existing account IDs etc.) and such a validator is not implemented yet (but can be implemented in a follow-up change). Change-Id: Id9e5574a1d8d82f4f48fbb0b6dadc0e27d138a28 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
parent
7cd6a74556
commit
276b8a897f
|
@ -109,7 +109,7 @@ public class AccountCreator {
|
||||||
if (email != null) {
|
if (email != null) {
|
||||||
extIds.add(ExternalId.createEmail(id, email));
|
extIds.add(ExternalId.createEmail(id, email));
|
||||||
}
|
}
|
||||||
externalIdsUpdate.create().insert(db, extIds);
|
externalIdsUpdate.create().insert(extIds);
|
||||||
|
|
||||||
Account a = new Account(id, TimeUtil.nowTs());
|
Account a = new Account(id, TimeUtil.nowTs());
|
||||||
a.setFullName(fullName);
|
a.setFullName(fullName);
|
||||||
|
|
|
@ -168,9 +168,9 @@ public class AccountIT extends AbstractDaemonTest {
|
||||||
// savedExternalIds is null when we don't run SSH tests and the assume in
|
// savedExternalIds is null when we don't run SSH tests and the assume in
|
||||||
// @Before in AbstractDaemonTest prevents this class' @Before method from
|
// @Before in AbstractDaemonTest prevents this class' @Before method from
|
||||||
// being executed.
|
// being executed.
|
||||||
externalIdsUpdate.delete(db, getExternalIds(admin));
|
externalIdsUpdate.delete(getExternalIds(admin));
|
||||||
externalIdsUpdate.delete(db, getExternalIds(user));
|
externalIdsUpdate.delete(getExternalIds(user));
|
||||||
externalIdsUpdate.insert(db, savedExternalIds);
|
externalIdsUpdate.insert(savedExternalIds);
|
||||||
}
|
}
|
||||||
accountCache.evict(admin.getId());
|
accountCache.evict(admin.getId());
|
||||||
accountCache.evict(user.getId());
|
accountCache.evict(user.getId());
|
||||||
|
@ -533,7 +533,7 @@ public class AccountIT extends AbstractDaemonTest {
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
ExternalId.createWithEmail(ExternalId.Key.parse(extId1), admin.id, email),
|
ExternalId.createWithEmail(ExternalId.Key.parse(extId1), admin.id, email),
|
||||||
ExternalId.createWithEmail(ExternalId.Key.parse(extId2), admin.id, email));
|
ExternalId.createWithEmail(ExternalId.Key.parse(extId2), admin.id, email));
|
||||||
externalIdsUpdateFactory.create().insert(db, extIds);
|
externalIdsUpdateFactory.create().insert(extIds);
|
||||||
accountCache.evict(admin.id);
|
accountCache.evict(admin.id);
|
||||||
accountIndexedCounter.assertReindexOf(admin);
|
accountIndexedCounter.assertReindexOf(admin);
|
||||||
assertThat(
|
assertThat(
|
||||||
|
@ -588,7 +588,7 @@ public class AccountIT extends AbstractDaemonTest {
|
||||||
String email = "foo.bar@example.com";
|
String email = "foo.bar@example.com";
|
||||||
externalIdsUpdateFactory
|
externalIdsUpdateFactory
|
||||||
.create()
|
.create()
|
||||||
.insert(db, ExternalId.createWithEmail(ExternalId.Key.parse("foo:bar"), admin.id, email));
|
.insert(ExternalId.createWithEmail(ExternalId.Key.parse("foo:bar"), admin.id, email));
|
||||||
accountCache.evict(admin.id);
|
accountCache.evict(admin.id);
|
||||||
assertEmail(byEmailCache.get(email), admin);
|
assertEmail(byEmailCache.get(email), admin);
|
||||||
|
|
||||||
|
@ -830,7 +830,7 @@ public class AccountIT extends AbstractDaemonTest {
|
||||||
public void addOtherUsersGpgKey_Conflict() throws Exception {
|
public void addOtherUsersGpgKey_Conflict() throws Exception {
|
||||||
// Both users have a matching external ID for this key.
|
// Both users have a matching external ID for this key.
|
||||||
addExternalIdEmail(admin, "test5@example.com");
|
addExternalIdEmail(admin, "test5@example.com");
|
||||||
externalIdsUpdate.insert(db, ExternalId.create("foo", "myId", user.getId()));
|
externalIdsUpdate.insert(ExternalId.create("foo", "myId", user.getId()));
|
||||||
accountCache.evict(user.getId());
|
accountCache.evict(user.getId());
|
||||||
accountIndexedCounter.assertReindexOf(user);
|
accountIndexedCounter.assertReindexOf(user);
|
||||||
|
|
||||||
|
@ -1043,7 +1043,7 @@ public class AccountIT extends AbstractDaemonTest {
|
||||||
expected.transform(k -> BaseEncoding.base16().encode(k.getPublicKey().getFingerprint()));
|
expected.transform(k -> BaseEncoding.base16().encode(k.getPublicKey().getFingerprint()));
|
||||||
Iterable<String> actualFps =
|
Iterable<String> actualFps =
|
||||||
externalIds
|
externalIds
|
||||||
.byAccount(db, currAccountId, SCHEME_GPGKEY)
|
.byAccount(currAccountId, SCHEME_GPGKEY)
|
||||||
.stream()
|
.stream()
|
||||||
.map(e -> e.key().id())
|
.map(e -> e.key().id())
|
||||||
.collect(toSet());
|
.collect(toSet());
|
||||||
|
@ -1072,7 +1072,7 @@ public class AccountIT extends AbstractDaemonTest {
|
||||||
private void addExternalIdEmail(TestAccount account, String email) throws Exception {
|
private void addExternalIdEmail(TestAccount account, String email) throws Exception {
|
||||||
checkNotNull(email);
|
checkNotNull(email);
|
||||||
externalIdsUpdate.insert(
|
externalIdsUpdate.insert(
|
||||||
db, ExternalId.createWithEmail(name("test"), email, account.getId(), email));
|
ExternalId.createWithEmail(name("test"), email, account.getId(), email));
|
||||||
// Clear saved AccountState and ExternalIds.
|
// Clear saved AccountState and ExternalIds.
|
||||||
accountCache.evict(account.getId());
|
accountCache.evict(account.getId());
|
||||||
accountIndexedCounter.assertReindexOf(account);
|
accountIndexedCounter.assertReindexOf(account);
|
||||||
|
|
|
@ -29,7 +29,6 @@ import com.github.rholder.retry.RetryerBuilder;
|
||||||
import com.github.rholder.retry.StopStrategies;
|
import com.github.rholder.retry.StopStrategies;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
import com.google.gerrit.acceptance.GerritConfig;
|
|
||||||
import com.google.gerrit.acceptance.PushOneCommit;
|
import com.google.gerrit.acceptance.PushOneCommit;
|
||||||
import com.google.gerrit.acceptance.RestResponse;
|
import com.google.gerrit.acceptance.RestResponse;
|
||||||
import com.google.gerrit.acceptance.Sandboxed;
|
import com.google.gerrit.acceptance.Sandboxed;
|
||||||
|
@ -209,7 +208,6 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@GerritConfig(name = "user.readExternalIdsFromGit", value = "true")
|
|
||||||
public void readExternalIdsWhenInvalidExternalIdsExist() throws Exception {
|
public void readExternalIdsWhenInvalidExternalIdsExist() throws Exception {
|
||||||
allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
|
allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
|
||||||
resetCurrentApiUser();
|
resetCurrentApiUser();
|
||||||
|
@ -217,15 +215,15 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
insertValidExternalIds();
|
insertValidExternalIds();
|
||||||
insertInvalidButParsableExternalIds();
|
insertInvalidButParsableExternalIds();
|
||||||
|
|
||||||
Set<ExternalId> parseableExtIds = externalIds.all(db);
|
Set<ExternalId> parseableExtIds = externalIds.all();
|
||||||
|
|
||||||
insertNonParsableExternalIds();
|
insertNonParsableExternalIds();
|
||||||
|
|
||||||
Set<ExternalId> extIds = externalIds.all(db);
|
Set<ExternalId> extIds = externalIds.all();
|
||||||
assertThat(extIds).containsExactlyElementsIn(parseableExtIds);
|
assertThat(extIds).containsExactlyElementsIn(parseableExtIds);
|
||||||
|
|
||||||
for (ExternalId parseableExtId : parseableExtIds) {
|
for (ExternalId parseableExtId : parseableExtIds) {
|
||||||
ExternalId extId = externalIds.get(db, parseableExtId.key());
|
ExternalId extId = externalIds.get(parseableExtId.key());
|
||||||
assertThat(extId).isEqualTo(parseableExtId);
|
assertThat(extId).isEqualTo(parseableExtId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,13 +268,12 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
|
|
||||||
// create valid external IDs
|
// create valid external IDs
|
||||||
u.insert(
|
u.insert(
|
||||||
db,
|
|
||||||
ExternalId.createWithPassword(
|
ExternalId.createWithPassword(
|
||||||
ExternalId.Key.parse(nextId(scheme, i)),
|
ExternalId.Key.parse(nextId(scheme, i)),
|
||||||
admin.id,
|
admin.id,
|
||||||
"admin.other@example.com",
|
"admin.other@example.com",
|
||||||
"secret-password"));
|
"secret-password"));
|
||||||
u.insert(db, createExternalIdWithOtherCaseEmail(nextId(scheme, i)));
|
u.insert(createExternalIdWithOtherCaseEmail(nextId(scheme, i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<ConsistencyProblemInfo> insertInvalidButParsableExternalIds()
|
private Set<ConsistencyProblemInfo> insertInvalidButParsableExternalIds()
|
||||||
|
@ -288,7 +285,7 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
Set<ConsistencyProblemInfo> expectedProblems = new HashSet<>();
|
Set<ConsistencyProblemInfo> expectedProblems = new HashSet<>();
|
||||||
ExternalId extIdForNonExistingAccount =
|
ExternalId extIdForNonExistingAccount =
|
||||||
createExternalIdForNonExistingAccount(nextId(scheme, i));
|
createExternalIdForNonExistingAccount(nextId(scheme, i));
|
||||||
u.insert(db, extIdForNonExistingAccount);
|
u.insert(extIdForNonExistingAccount);
|
||||||
expectedProblems.add(
|
expectedProblems.add(
|
||||||
consistencyError(
|
consistencyError(
|
||||||
"External ID '"
|
"External ID '"
|
||||||
|
@ -297,7 +294,7 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
+ extIdForNonExistingAccount.accountId().get()));
|
+ extIdForNonExistingAccount.accountId().get()));
|
||||||
|
|
||||||
ExternalId extIdWithInvalidEmail = createExternalIdWithInvalidEmail(nextId(scheme, i));
|
ExternalId extIdWithInvalidEmail = createExternalIdWithInvalidEmail(nextId(scheme, i));
|
||||||
u.insert(db, extIdWithInvalidEmail);
|
u.insert(extIdWithInvalidEmail);
|
||||||
expectedProblems.add(
|
expectedProblems.add(
|
||||||
consistencyError(
|
consistencyError(
|
||||||
"External ID '"
|
"External ID '"
|
||||||
|
@ -306,7 +303,7 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
+ extIdWithInvalidEmail.email()));
|
+ extIdWithInvalidEmail.email()));
|
||||||
|
|
||||||
ExternalId extIdWithDuplicateEmail = createExternalIdWithDuplicateEmail(nextId(scheme, i));
|
ExternalId extIdWithDuplicateEmail = createExternalIdWithDuplicateEmail(nextId(scheme, i));
|
||||||
u.insert(db, extIdWithDuplicateEmail);
|
u.insert(extIdWithDuplicateEmail);
|
||||||
expectedProblems.add(
|
expectedProblems.add(
|
||||||
consistencyError(
|
consistencyError(
|
||||||
"Email '"
|
"Email '"
|
||||||
|
@ -318,7 +315,7 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
+ "'"));
|
+ "'"));
|
||||||
|
|
||||||
ExternalId extIdWithBadPassword = createExternalIdWithBadPassword("admin-username");
|
ExternalId extIdWithBadPassword = createExternalIdWithBadPassword("admin-username");
|
||||||
u.insert(db, extIdWithBadPassword);
|
u.insert(extIdWithBadPassword);
|
||||||
expectedProblems.add(
|
expectedProblems.add(
|
||||||
consistencyError(
|
consistencyError(
|
||||||
"External ID '"
|
"External ID '"
|
||||||
|
@ -508,7 +505,7 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
() -> {
|
() -> {
|
||||||
if (!doneBgUpdate.getAndSet(true)) {
|
if (!doneBgUpdate.getAndSet(true)) {
|
||||||
try {
|
try {
|
||||||
extIdsUpdate.create().insert(db, ExternalId.create(barId, admin.id));
|
extIdsUpdate.create().insert(ExternalId.create(barId, admin.id));
|
||||||
} catch (IOException | ConfigInvalidException | OrmException e) {
|
} catch (IOException | ConfigInvalidException | OrmException e) {
|
||||||
// Ignore, the successful insertion of the external ID is asserted later
|
// Ignore, the successful insertion of the external ID is asserted later
|
||||||
}
|
}
|
||||||
|
@ -516,11 +513,11 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
},
|
},
|
||||||
retryer);
|
retryer);
|
||||||
assertThat(doneBgUpdate.get()).isFalse();
|
assertThat(doneBgUpdate.get()).isFalse();
|
||||||
update.insert(db, ExternalId.create(fooId, admin.id));
|
update.insert(ExternalId.create(fooId, admin.id));
|
||||||
assertThat(doneBgUpdate.get()).isTrue();
|
assertThat(doneBgUpdate.get()).isTrue();
|
||||||
|
|
||||||
assertThat(externalIds.get(db, fooId)).isNotNull();
|
assertThat(externalIds.get(fooId)).isNotNull();
|
||||||
assertThat(externalIds.get(db, barId)).isNotNull();
|
assertThat(externalIds.get(barId)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -544,7 +541,7 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
try {
|
try {
|
||||||
extIdsUpdate
|
extIdsUpdate
|
||||||
.create()
|
.create()
|
||||||
.insert(db, ExternalId.create(extIdsKeys[bgCounter.getAndAdd(1)], admin.id));
|
.insert(ExternalId.create(extIdsKeys[bgCounter.getAndAdd(1)], admin.id));
|
||||||
} catch (IOException | ConfigInvalidException | OrmException e) {
|
} catch (IOException | ConfigInvalidException | OrmException e) {
|
||||||
// Ignore, the successful insertion of the external ID is asserted later
|
// Ignore, the successful insertion of the external ID is asserted later
|
||||||
}
|
}
|
||||||
|
@ -555,14 +552,14 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
.build());
|
.build());
|
||||||
assertThat(bgCounter.get()).isEqualTo(0);
|
assertThat(bgCounter.get()).isEqualTo(0);
|
||||||
try {
|
try {
|
||||||
update.insert(db, ExternalId.create(ExternalId.Key.create("abc", "abc"), admin.id));
|
update.insert(ExternalId.create(ExternalId.Key.create("abc", "abc"), admin.id));
|
||||||
fail("expected LockFailureException");
|
fail("expected LockFailureException");
|
||||||
} catch (LockFailureException e) {
|
} catch (LockFailureException e) {
|
||||||
// Ignore, expected
|
// Ignore, expected
|
||||||
}
|
}
|
||||||
assertThat(bgCounter.get()).isEqualTo(extIdsKeys.length);
|
assertThat(bgCounter.get()).isEqualTo(extIdsKeys.length);
|
||||||
for (ExternalId.Key extIdKey : extIdsKeys) {
|
for (ExternalId.Key extIdKey : extIdsKeys) {
|
||||||
assertThat(externalIds.get(db, extIdKey)).isNotNull();
|
assertThat(externalIds.get(extIdKey)).isNotNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,38 +567,36 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
public void readExternalIdWithAccountIdThatCanBeExpressedInKiB() throws Exception {
|
public void readExternalIdWithAccountIdThatCanBeExpressedInKiB() throws Exception {
|
||||||
ExternalId.Key extIdKey = ExternalId.Key.parse("foo:bar");
|
ExternalId.Key extIdKey = ExternalId.Key.parse("foo:bar");
|
||||||
Account.Id accountId = new Account.Id(1024 * 100);
|
Account.Id accountId = new Account.Id(1024 * 100);
|
||||||
extIdsUpdate.create().insert(db, ExternalId.create(extIdKey, accountId));
|
extIdsUpdate.create().insert(ExternalId.create(extIdKey, accountId));
|
||||||
ExternalId extId = externalIds.get(db, extIdKey);
|
ExternalId extId = externalIds.get(extIdKey);
|
||||||
assertThat(extId.accountId()).isEqualTo(accountId);
|
assertThat(extId.accountId()).isEqualTo(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@GerritConfig(name = "user.readExternalIdsFromGit", value = "true")
|
|
||||||
public void checkNoReloadAfterUpdate() throws Exception {
|
public void checkNoReloadAfterUpdate() throws Exception {
|
||||||
Set<ExternalId> expectedExtIds = new HashSet<>(externalIds.byAccount(db, admin.id));
|
Set<ExternalId> expectedExtIds = new HashSet<>(externalIds.byAccount(admin.id));
|
||||||
externalIdReader.setFailOnLoad(true);
|
externalIdReader.setFailOnLoad(true);
|
||||||
|
|
||||||
// insert external ID
|
// insert external ID
|
||||||
ExternalId extId = ExternalId.create("foo", "bar", admin.id);
|
ExternalId extId = ExternalId.create("foo", "bar", admin.id);
|
||||||
extIdsUpdate.create().insert(db, extId);
|
extIdsUpdate.create().insert(extId);
|
||||||
expectedExtIds.add(extId);
|
expectedExtIds.add(extId);
|
||||||
assertThat(externalIds.byAccount(db, admin.id)).containsExactlyElementsIn(expectedExtIds);
|
assertThat(externalIds.byAccount(admin.id)).containsExactlyElementsIn(expectedExtIds);
|
||||||
|
|
||||||
// update external ID
|
// update external ID
|
||||||
expectedExtIds.remove(extId);
|
expectedExtIds.remove(extId);
|
||||||
extId = ExternalId.createWithEmail("foo", "bar", admin.id, "foo.bar@example.com");
|
extId = ExternalId.createWithEmail("foo", "bar", admin.id, "foo.bar@example.com");
|
||||||
extIdsUpdate.create().upsert(db, extId);
|
extIdsUpdate.create().upsert(extId);
|
||||||
expectedExtIds.add(extId);
|
expectedExtIds.add(extId);
|
||||||
assertThat(externalIds.byAccount(db, admin.id)).containsExactlyElementsIn(expectedExtIds);
|
assertThat(externalIds.byAccount(admin.id)).containsExactlyElementsIn(expectedExtIds);
|
||||||
|
|
||||||
// delete external ID
|
// delete external ID
|
||||||
extIdsUpdate.create().delete(db, extId);
|
extIdsUpdate.create().delete(extId);
|
||||||
expectedExtIds.remove(extId);
|
expectedExtIds.remove(extId);
|
||||||
assertThat(externalIds.byAccount(db, admin.id)).containsExactlyElementsIn(expectedExtIds);
|
assertThat(externalIds.byAccount(admin.id)).containsExactlyElementsIn(expectedExtIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@GerritConfig(name = "user.readExternalIdsFromGit", value = "true")
|
|
||||||
public void byAccountFailIfReadingExternalIdsFails() throws Exception {
|
public void byAccountFailIfReadingExternalIdsFails() throws Exception {
|
||||||
externalIdReader.setFailOnLoad(true);
|
externalIdReader.setFailOnLoad(true);
|
||||||
|
|
||||||
|
@ -609,11 +604,10 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
insertExtIdBehindGerritsBack(ExternalId.create("foo", "bar", admin.id));
|
insertExtIdBehindGerritsBack(ExternalId.create("foo", "bar", admin.id));
|
||||||
|
|
||||||
exception.expect(IOException.class);
|
exception.expect(IOException.class);
|
||||||
externalIds.byAccount(db, admin.id);
|
externalIds.byAccount(admin.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@GerritConfig(name = "user.readExternalIdsFromGit", value = "true")
|
|
||||||
public void byEmailFailIfReadingExternalIdsFails() throws Exception {
|
public void byEmailFailIfReadingExternalIdsFails() throws Exception {
|
||||||
externalIdReader.setFailOnLoad(true);
|
externalIdReader.setFailOnLoad(true);
|
||||||
|
|
||||||
|
@ -621,17 +615,16 @@ public class ExternalIdIT extends AbstractDaemonTest {
|
||||||
insertExtIdBehindGerritsBack(ExternalId.create("foo", "bar", admin.id));
|
insertExtIdBehindGerritsBack(ExternalId.create("foo", "bar", admin.id));
|
||||||
|
|
||||||
exception.expect(IOException.class);
|
exception.expect(IOException.class);
|
||||||
externalIds.byEmail(db, admin.email);
|
externalIds.byEmail(admin.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@GerritConfig(name = "user.readExternalIdsFromGit", value = "true")
|
|
||||||
public void byAccountUpdateExternalIdsBehindGerritsBack() throws Exception {
|
public void byAccountUpdateExternalIdsBehindGerritsBack() throws Exception {
|
||||||
Set<ExternalId> expectedExternalIds = new HashSet<>(externalIds.byAccount(db, admin.id));
|
Set<ExternalId> expectedExternalIds = new HashSet<>(externalIds.byAccount(admin.id));
|
||||||
ExternalId newExtId = ExternalId.create("foo", "bar", admin.id);
|
ExternalId newExtId = ExternalId.create("foo", "bar", admin.id);
|
||||||
insertExtIdBehindGerritsBack(newExtId);
|
insertExtIdBehindGerritsBack(newExtId);
|
||||||
expectedExternalIds.add(newExtId);
|
expectedExternalIds.add(newExtId);
|
||||||
assertThat(externalIds.byAccount(db, admin.id)).containsExactlyElementsIn(expectedExternalIds);
|
assertThat(externalIds.byAccount(admin.id)).containsExactlyElementsIn(expectedExternalIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertExtIdBehindGerritsBack(ExternalId extId) throws Exception {
|
private void insertExtIdBehindGerritsBack(ExternalId extId) throws Exception {
|
||||||
|
|
|
@ -23,7 +23,6 @@ import com.google.gerrit.extensions.restapi.Response;
|
||||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
import com.google.gerrit.gpg.PublicKeyStore;
|
import com.google.gerrit.gpg.PublicKeyStore;
|
||||||
import com.google.gerrit.gpg.server.DeleteGpgKey.Input;
|
import com.google.gerrit.gpg.server.DeleteGpgKey.Input;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.account.AccountCache;
|
import com.google.gerrit.server.account.AccountCache;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
|
@ -43,7 +42,6 @@ public class DeleteGpgKey implements RestModifyView<GpgKey, Input> {
|
||||||
public static class Input {}
|
public static class Input {}
|
||||||
|
|
||||||
private final Provider<PersonIdent> serverIdent;
|
private final Provider<PersonIdent> serverIdent;
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
private final Provider<PublicKeyStore> storeProvider;
|
private final Provider<PublicKeyStore> storeProvider;
|
||||||
private final AccountCache accountCache;
|
private final AccountCache accountCache;
|
||||||
private final ExternalIdsUpdate.User externalIdsUpdateFactory;
|
private final ExternalIdsUpdate.User externalIdsUpdateFactory;
|
||||||
|
@ -51,12 +49,10 @@ public class DeleteGpgKey implements RestModifyView<GpgKey, Input> {
|
||||||
@Inject
|
@Inject
|
||||||
DeleteGpgKey(
|
DeleteGpgKey(
|
||||||
@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
||||||
Provider<ReviewDb> db,
|
|
||||||
Provider<PublicKeyStore> storeProvider,
|
Provider<PublicKeyStore> storeProvider,
|
||||||
AccountCache accountCache,
|
AccountCache accountCache,
|
||||||
ExternalIdsUpdate.User externalIdsUpdateFactory) {
|
ExternalIdsUpdate.User externalIdsUpdateFactory) {
|
||||||
this.serverIdent = serverIdent;
|
this.serverIdent = serverIdent;
|
||||||
this.db = db;
|
|
||||||
this.storeProvider = storeProvider;
|
this.storeProvider = storeProvider;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
this.externalIdsUpdateFactory = externalIdsUpdateFactory;
|
this.externalIdsUpdateFactory = externalIdsUpdateFactory;
|
||||||
|
@ -70,7 +66,6 @@ public class DeleteGpgKey implements RestModifyView<GpgKey, Input> {
|
||||||
externalIdsUpdateFactory
|
externalIdsUpdateFactory
|
||||||
.create()
|
.create()
|
||||||
.delete(
|
.delete(
|
||||||
db.get(),
|
|
||||||
rsrc.getUser().getAccountId(),
|
rsrc.getUser().getAccountId(),
|
||||||
ExternalId.Key.create(
|
ExternalId.Key.create(
|
||||||
SCHEME_GPGKEY, BaseEncoding.base16().encode(key.getFingerprint())));
|
SCHEME_GPGKEY, BaseEncoding.base16().encode(key.getFingerprint())));
|
||||||
|
|
|
@ -34,7 +34,6 @@ import com.google.gerrit.gpg.Fingerprint;
|
||||||
import com.google.gerrit.gpg.GerritPublicKeyChecker;
|
import com.google.gerrit.gpg.GerritPublicKeyChecker;
|
||||||
import com.google.gerrit.gpg.PublicKeyChecker;
|
import com.google.gerrit.gpg.PublicKeyChecker;
|
||||||
import com.google.gerrit.gpg.PublicKeyStore;
|
import com.google.gerrit.gpg.PublicKeyStore;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.AccountResource;
|
import com.google.gerrit.server.account.AccountResource;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
|
@ -64,7 +63,6 @@ public class GpgKeys implements ChildCollection<AccountResource, GpgKey> {
|
||||||
public static final String MIME_TYPE = "application/pgp-keys";
|
public static final String MIME_TYPE = "application/pgp-keys";
|
||||||
|
|
||||||
private final DynamicMap<RestView<GpgKey>> views;
|
private final DynamicMap<RestView<GpgKey>> views;
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final Provider<PublicKeyStore> storeProvider;
|
private final Provider<PublicKeyStore> storeProvider;
|
||||||
private final GerritPublicKeyChecker.Factory checkerFactory;
|
private final GerritPublicKeyChecker.Factory checkerFactory;
|
||||||
|
@ -73,13 +71,11 @@ public class GpgKeys implements ChildCollection<AccountResource, GpgKey> {
|
||||||
@Inject
|
@Inject
|
||||||
GpgKeys(
|
GpgKeys(
|
||||||
DynamicMap<RestView<GpgKey>> views,
|
DynamicMap<RestView<GpgKey>> views,
|
||||||
Provider<ReviewDb> db,
|
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
Provider<PublicKeyStore> storeProvider,
|
Provider<PublicKeyStore> storeProvider,
|
||||||
GerritPublicKeyChecker.Factory checkerFactory,
|
GerritPublicKeyChecker.Factory checkerFactory,
|
||||||
ExternalIds externalIds) {
|
ExternalIds externalIds) {
|
||||||
this.views = views;
|
this.views = views;
|
||||||
this.db = db;
|
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.storeProvider = storeProvider;
|
this.storeProvider = storeProvider;
|
||||||
this.checkerFactory = checkerFactory;
|
this.checkerFactory = checkerFactory;
|
||||||
|
@ -199,8 +195,8 @@ public class GpgKeys implements ChildCollection<AccountResource, GpgKey> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterable<ExternalId> getGpgExtIds(AccountResource rsrc) throws IOException, OrmException {
|
private Iterable<ExternalId> getGpgExtIds(AccountResource rsrc) throws IOException {
|
||||||
return externalIds.byAccount(db.get(), rsrc.getUser().getAccountId(), SCHEME_GPGKEY);
|
return externalIds.byAccount(rsrc.getUser().getAccountId(), SCHEME_GPGKEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long keyId(byte[] fp) {
|
private static long keyId(byte[] fp) {
|
||||||
|
|
|
@ -40,7 +40,6 @@ import com.google.gerrit.gpg.PublicKeyChecker;
|
||||||
import com.google.gerrit.gpg.PublicKeyStore;
|
import com.google.gerrit.gpg.PublicKeyStore;
|
||||||
import com.google.gerrit.gpg.server.PostGpgKeys.Input;
|
import com.google.gerrit.gpg.server.PostGpgKeys.Input;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
@ -85,7 +84,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||||
|
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
private final Provider<PersonIdent> serverIdent;
|
private final Provider<PersonIdent> serverIdent;
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final Provider<PublicKeyStore> storeProvider;
|
private final Provider<PublicKeyStore> storeProvider;
|
||||||
private final GerritPublicKeyChecker.Factory checkerFactory;
|
private final GerritPublicKeyChecker.Factory checkerFactory;
|
||||||
|
@ -98,7 +96,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||||
@Inject
|
@Inject
|
||||||
PostGpgKeys(
|
PostGpgKeys(
|
||||||
@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
||||||
Provider<ReviewDb> db,
|
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
Provider<PublicKeyStore> storeProvider,
|
Provider<PublicKeyStore> storeProvider,
|
||||||
GerritPublicKeyChecker.Factory checkerFactory,
|
GerritPublicKeyChecker.Factory checkerFactory,
|
||||||
|
@ -108,7 +105,6 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||||
ExternalIds externalIds,
|
ExternalIds externalIds,
|
||||||
ExternalIdsUpdate.User externalIdsUpdateFactory) {
|
ExternalIdsUpdate.User externalIdsUpdateFactory) {
|
||||||
this.serverIdent = serverIdent;
|
this.serverIdent = serverIdent;
|
||||||
this.db = db;
|
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.storeProvider = storeProvider;
|
this.storeProvider = storeProvider;
|
||||||
this.checkerFactory = checkerFactory;
|
this.checkerFactory = checkerFactory;
|
||||||
|
@ -126,7 +122,7 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||||
GpgKeys.checkVisible(self, rsrc);
|
GpgKeys.checkVisible(self, rsrc);
|
||||||
|
|
||||||
Collection<ExternalId> existingExtIds =
|
Collection<ExternalId> existingExtIds =
|
||||||
externalIds.byAccount(db.get(), rsrc.getUser().getAccountId(), SCHEME_GPGKEY);
|
externalIds.byAccount(rsrc.getUser().getAccountId(), SCHEME_GPGKEY);
|
||||||
try (PublicKeyStore store = storeProvider.get()) {
|
try (PublicKeyStore store = storeProvider.get()) {
|
||||||
Set<Fingerprint> toRemove = readKeysToRemove(input, existingExtIds);
|
Set<Fingerprint> toRemove = readKeysToRemove(input, existingExtIds);
|
||||||
List<PGPPublicKeyRing> newKeys = readKeysToAdd(input, toRemove);
|
List<PGPPublicKeyRing> newKeys = readKeysToAdd(input, toRemove);
|
||||||
|
@ -151,7 +147,7 @@ public class PostGpgKeys implements RestModifyView<AccountResource, Input> {
|
||||||
toRemove.stream().map(fp -> toExtIdKey(fp.get())).collect(toList());
|
toRemove.stream().map(fp -> toExtIdKey(fp.get())).collect(toList());
|
||||||
externalIdsUpdateFactory
|
externalIdsUpdateFactory
|
||||||
.create()
|
.create()
|
||||||
.replace(db.get(), rsrc.getUser().getAccountId(), extIdKeysToRemove, newExtIds);
|
.replace(rsrc.getUser().getAccountId(), extIdKeysToRemove, newExtIds);
|
||||||
accountCache.evict(rsrc.getUser().getAccountId());
|
accountCache.evict(rsrc.getUser().getAccountId());
|
||||||
return toJson(newKeys, toRemove, store, rsrc.getUser());
|
return toJson(newKeys, toRemove, store, rsrc.getUser());
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,7 +223,7 @@ public class GerritPublicKeyCheckerTest {
|
||||||
@Test
|
@Test
|
||||||
public void noExternalIds() throws Exception {
|
public void noExternalIds() throws Exception {
|
||||||
ExternalIdsUpdate externalIdsUpdate = externalIdsUpdateFactory.create();
|
ExternalIdsUpdate externalIdsUpdate = externalIdsUpdateFactory.create();
|
||||||
externalIdsUpdate.deleteAll(db, user.getAccountId());
|
externalIdsUpdate.deleteAll(user.getAccountId());
|
||||||
reloadUser();
|
reloadUser();
|
||||||
|
|
||||||
TestKey key = validKeyWithSecondUserId();
|
TestKey key = validKeyWithSecondUserId();
|
||||||
|
@ -237,7 +237,7 @@ public class GerritPublicKeyCheckerTest {
|
||||||
assertProblems(
|
assertProblems(
|
||||||
checker.check(key.getPublicKey()), Status.BAD, "Key is not associated with any users");
|
checker.check(key.getPublicKey()), Status.BAD, "Key is not associated with any users");
|
||||||
externalIdsUpdate.insert(
|
externalIdsUpdate.insert(
|
||||||
db, ExternalId.create(toExtIdKey(key.getPublicKey()), user.getAccountId()));
|
ExternalId.create(toExtIdKey(key.getPublicKey()), user.getAccountId()));
|
||||||
reloadUser();
|
reloadUser();
|
||||||
assertProblems(checker.check(key.getPublicKey()), Status.BAD, "No identities found for user");
|
assertProblems(checker.check(key.getPublicKey()), Status.BAD, "No identities found for user");
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ public class GerritPublicKeyCheckerTest {
|
||||||
cb.setCommitter(ident);
|
cb.setCommitter(ident);
|
||||||
assertThat(store.save(cb)).isAnyOf(NEW, FAST_FORWARD, FORCED);
|
assertThat(store.save(cb)).isAnyOf(NEW, FAST_FORWARD, FORCED);
|
||||||
|
|
||||||
externalIdsUpdateFactory.create().insert(db, newExtIds);
|
externalIdsUpdateFactory.create().insert(newExtIds);
|
||||||
accountCache.evict(user.getAccountId());
|
accountCache.evict(user.getAccountId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +432,7 @@ public class GerritPublicKeyCheckerTest {
|
||||||
private void addExternalId(String scheme, String id, String email) throws Exception {
|
private void addExternalId(String scheme, String id, String email) throws Exception {
|
||||||
externalIdsUpdateFactory
|
externalIdsUpdateFactory
|
||||||
.create()
|
.create()
|
||||||
.insert(db, ExternalId.createWithEmail(scheme, id, user.getAccountId(), email));
|
.insert(ExternalId.createWithEmail(scheme, id, user.getAccountId(), email));
|
||||||
reloadUser();
|
reloadUser();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,11 @@ import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_U
|
||||||
|
|
||||||
import com.google.gerrit.lifecycle.LifecycleManager;
|
import com.google.gerrit.lifecycle.LifecycleManager;
|
||||||
import com.google.gerrit.pgm.util.SiteProgram;
|
import com.google.gerrit.pgm.util.SiteProgram;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.account.externalids.DisabledExternalIdCache;
|
import com.google.gerrit.server.account.externalids.DisabledExternalIdCache;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIds;
|
import com.google.gerrit.server.account.externalids.ExternalIds;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIdsBatchUpdate;
|
import com.google.gerrit.server.account.externalids.ExternalIdsBatchUpdate;
|
||||||
import com.google.gerrit.server.schema.SchemaVersionCheck;
|
import com.google.gerrit.server.schema.SchemaVersionCheck;
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -38,8 +36,6 @@ public class LocalUsernamesToLowerCase extends SiteProgram {
|
||||||
private final LifecycleManager manager = new LifecycleManager();
|
private final LifecycleManager manager = new LifecycleManager();
|
||||||
private final TextProgressMonitor monitor = new TextProgressMonitor();
|
private final TextProgressMonitor monitor = new TextProgressMonitor();
|
||||||
|
|
||||||
@Inject private SchemaFactory<ReviewDb> database;
|
|
||||||
|
|
||||||
@Inject private ExternalIds externalIds;
|
@Inject private ExternalIds externalIds;
|
||||||
|
|
||||||
@Inject private ExternalIdsBatchUpdate externalIdsBatchUpdate;
|
@Inject private ExternalIdsBatchUpdate externalIdsBatchUpdate;
|
||||||
|
@ -63,19 +59,17 @@ public class LocalUsernamesToLowerCase extends SiteProgram {
|
||||||
})
|
})
|
||||||
.injectMembers(this);
|
.injectMembers(this);
|
||||||
|
|
||||||
try (ReviewDb db = database.open()) {
|
Collection<ExternalId> todo = externalIds.all();
|
||||||
Collection<ExternalId> todo = externalIds.all(db);
|
monitor.beginTask("Converting local usernames", todo.size());
|
||||||
monitor.beginTask("Converting local usernames", todo.size());
|
|
||||||
|
|
||||||
for (ExternalId extId : todo) {
|
for (ExternalId extId : todo) {
|
||||||
convertLocalUserToLowerCase(extId);
|
convertLocalUserToLowerCase(extId);
|
||||||
monitor.update(1);
|
monitor.update(1);
|
||||||
}
|
|
||||||
|
|
||||||
externalIdsBatchUpdate.commit(db, "Convert local usernames to lower case");
|
|
||||||
monitor.endTask();
|
|
||||||
manager.stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
externalIdsBatchUpdate.commit("Convert local usernames to lower case");
|
||||||
|
monitor.endTask();
|
||||||
|
manager.stop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,7 @@
|
||||||
|
|
||||||
package com.google.gerrit.pgm.init;
|
package com.google.gerrit.pgm.init;
|
||||||
|
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalId.toAccountExternalIds;
|
|
||||||
|
|
||||||
import com.google.gerrit.pgm.init.api.InitFlags;
|
import com.google.gerrit.pgm.init.api.InitFlags;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.GerritPersonIdentProvider;
|
import com.google.gerrit.server.GerritPersonIdentProvider;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIdReader;
|
import com.google.gerrit.server.account.externalids.ExternalIdReader;
|
||||||
|
@ -52,9 +49,8 @@ public class ExternalIdsOnInit {
|
||||||
this.allUsers = allUsers.get();
|
this.allUsers = allUsers.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void insert(ReviewDb db, String commitMessage, Collection<ExternalId> extIds)
|
public synchronized void insert(String commitMessage, Collection<ExternalId> extIds)
|
||||||
throws OrmException, IOException, ConfigInvalidException {
|
throws OrmException, IOException, ConfigInvalidException {
|
||||||
db.accountExternalIds().insert(toAccountExternalIds(extIds));
|
|
||||||
|
|
||||||
File path = getPath();
|
File path = getPath();
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class InitAdminUser implements InitStep {
|
||||||
if (email != null) {
|
if (email != null) {
|
||||||
extIds.add(ExternalId.createEmail(id, email));
|
extIds.add(ExternalId.createEmail(id, email));
|
||||||
}
|
}
|
||||||
externalIds.insert(db, "Add external IDs for initial admin user", extIds);
|
externalIds.insert("Add external IDs for initial admin user", extIds);
|
||||||
|
|
||||||
Account a = new Account(id, TimeUtil.nowTs());
|
Account a = new Account(id, TimeUtil.nowTs());
|
||||||
a.setFullName(name);
|
a.setFullName(name);
|
||||||
|
|
|
@ -1,186 +0,0 @@
|
||||||
// Copyright (C) 2008 The Android Open Source Project
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package com.google.gerrit.reviewdb.client;
|
|
||||||
|
|
||||||
import com.google.gerrit.extensions.client.AuthType;
|
|
||||||
import com.google.gwtorm.client.Column;
|
|
||||||
import com.google.gwtorm.client.StringKey;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/** Association of an external account identifier to a local {@link Account}. */
|
|
||||||
public final class AccountExternalId {
|
|
||||||
/**
|
|
||||||
* Scheme used for {@link AuthType#LDAP}, {@link AuthType#CLIENT_SSL_CERT_LDAP}, {@link
|
|
||||||
* AuthType#HTTP_LDAP}, and {@link AuthType#LDAP_BIND} usernames.
|
|
||||||
*
|
|
||||||
* <p>The name {@code gerrit:} was a very poor choice.
|
|
||||||
*/
|
|
||||||
public static final String SCHEME_GERRIT = "gerrit:";
|
|
||||||
|
|
||||||
/** Scheme used for randomly created identities constructed by a UUID. */
|
|
||||||
public static final String SCHEME_UUID = "uuid:";
|
|
||||||
|
|
||||||
/** Scheme used to represent only an email address. */
|
|
||||||
public static final String SCHEME_MAILTO = "mailto:";
|
|
||||||
|
|
||||||
/** Scheme for the username used to authenticate an account, e.g. over SSH. */
|
|
||||||
public static final String SCHEME_USERNAME = "username:";
|
|
||||||
|
|
||||||
/** Scheme used for GPG public keys. */
|
|
||||||
public static final String SCHEME_GPGKEY = "gpgkey:";
|
|
||||||
|
|
||||||
/** Scheme for external auth used during authentication, e.g. OAuth Token */
|
|
||||||
public static final String SCHEME_EXTERNAL = "external:";
|
|
||||||
|
|
||||||
public static class Key extends StringKey<com.google.gwtorm.client.Key<?>> {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Column(id = 1)
|
|
||||||
protected String externalId;
|
|
||||||
|
|
||||||
protected Key() {}
|
|
||||||
|
|
||||||
public Key(String scheme, final String identity) {
|
|
||||||
if (!scheme.endsWith(":")) {
|
|
||||||
scheme += ":";
|
|
||||||
}
|
|
||||||
externalId = scheme + identity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Key(final String e) {
|
|
||||||
externalId = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return externalId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void set(String newValue) {
|
|
||||||
externalId = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScheme() {
|
|
||||||
int c = externalId.indexOf(':');
|
|
||||||
return 0 < c ? externalId.substring(0, c) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Column(id = 1, name = Column.NONE)
|
|
||||||
protected Key key;
|
|
||||||
|
|
||||||
@Column(id = 2)
|
|
||||||
protected Account.Id accountId;
|
|
||||||
|
|
||||||
@Column(id = 3, notNull = false)
|
|
||||||
protected String emailAddress;
|
|
||||||
|
|
||||||
// Encoded version of the hashed and salted password, to be interpreted by the
|
|
||||||
// {@link HashedPassword} class.
|
|
||||||
@Column(id = 4, notNull = false)
|
|
||||||
protected String password;
|
|
||||||
|
|
||||||
/** <i>computed value</i> is this identity trusted by the site administrator? */
|
|
||||||
protected boolean trusted;
|
|
||||||
|
|
||||||
/** <i>computed value</i> can this identity be removed from the account? */
|
|
||||||
protected boolean canDelete;
|
|
||||||
|
|
||||||
protected AccountExternalId() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new binding to an external identity.
|
|
||||||
*
|
|
||||||
* @param who the account this binds to.
|
|
||||||
* @param k the binding key.
|
|
||||||
*/
|
|
||||||
public AccountExternalId(final Account.Id who, final AccountExternalId.Key k) {
|
|
||||||
accountId = who;
|
|
||||||
key = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccountExternalId.Key getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get local id of this account, to link with in other entities */
|
|
||||||
public Account.Id getAccountId() {
|
|
||||||
return accountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExternalId() {
|
|
||||||
return key.externalId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmailAddress() {
|
|
||||||
return emailAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmailAddress(final String e) {
|
|
||||||
emailAddress = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isScheme(final String scheme) {
|
|
||||||
final String id = getExternalId();
|
|
||||||
return id != null && id.startsWith(scheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSchemeRest() {
|
|
||||||
String scheme = key.getScheme();
|
|
||||||
return null != scheme ? getExternalId().substring(scheme.length() + 1) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String hashed) {
|
|
||||||
password = hashed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTrusted() {
|
|
||||||
return trusted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTrusted(final boolean t) {
|
|
||||||
trusted = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canDelete() {
|
|
||||||
return canDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCanDelete(final boolean t) {
|
|
||||||
canDelete = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o instanceof AccountExternalId) {
|
|
||||||
AccountExternalId extId = (AccountExternalId) o;
|
|
||||||
return Objects.equals(key, extId.key)
|
|
||||||
&& Objects.equals(accountId, extId.accountId)
|
|
||||||
&& Objects.equals(emailAddress, extId.emailAddress)
|
|
||||||
&& Objects.equals(password, extId.password);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(key, accountId, emailAddress, password);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
// Copyright (C) 2008 The Android Open Source Project
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package com.google.gerrit.reviewdb.server;
|
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
|
||||||
import com.google.gwtorm.server.Access;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
|
||||||
import com.google.gwtorm.server.PrimaryKey;
|
|
||||||
import com.google.gwtorm.server.Query;
|
|
||||||
import com.google.gwtorm.server.ResultSet;
|
|
||||||
|
|
||||||
public interface AccountExternalIdAccess extends Access<AccountExternalId, AccountExternalId.Key> {
|
|
||||||
@Override
|
|
||||||
@PrimaryKey("key")
|
|
||||||
AccountExternalId get(AccountExternalId.Key key) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE accountId = ?")
|
|
||||||
ResultSet<AccountExternalId> byAccount(Account.Id id) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE emailAddress = ?")
|
|
||||||
ResultSet<AccountExternalId> byEmailAddress(String email) throws OrmException;
|
|
||||||
|
|
||||||
@Query
|
|
||||||
ResultSet<AccountExternalId> all() throws OrmException;
|
|
||||||
}
|
|
|
@ -50,8 +50,7 @@ public interface ReviewDb extends Schema {
|
||||||
@Relation(id = 6)
|
@Relation(id = 6)
|
||||||
AccountAccess accounts();
|
AccountAccess accounts();
|
||||||
|
|
||||||
@Relation(id = 7)
|
// Deleted @Relation(id = 7)
|
||||||
AccountExternalIdAccess accountExternalIds();
|
|
||||||
|
|
||||||
// Deleted @Relation(id = 8)
|
// Deleted @Relation(id = 8)
|
||||||
|
|
||||||
|
|
|
@ -82,11 +82,6 @@ public class ReviewDbWrapper implements ReviewDb {
|
||||||
return delegate.accounts();
|
return delegate.accounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AccountExternalIdAccess accountExternalIds() {
|
|
||||||
return delegate.accountExternalIds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccountGroupAccess accountGroups() {
|
public AccountGroupAccess accountGroups() {
|
||||||
return delegate.accountGroups();
|
return delegate.accountGroups();
|
||||||
|
|
|
@ -15,16 +15,6 @@ CREATE INDEX accounts_byFullName
|
||||||
ON accounts (full_name);
|
ON accounts (full_name);
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
|
||||||
-- AccountExternalIdAccess
|
|
||||||
-- covers: byAccount
|
|
||||||
CREATE INDEX account_external_ids_byAccount
|
|
||||||
ON account_external_ids (account_id);
|
|
||||||
|
|
||||||
-- covers: byEmailAddress
|
|
||||||
CREATE INDEX account_external_ids_byEmail
|
|
||||||
ON account_external_ids (email_address);
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- AccountGroupMemberAccess
|
-- AccountGroupMemberAccess
|
||||||
-- @PrimaryKey covers: byAccount
|
-- @PrimaryKey covers: byAccount
|
||||||
|
|
|
@ -18,18 +18,6 @@ ON accounts (full_name)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
|
||||||
-- AccountExternalIdAccess
|
|
||||||
-- covers: byAccount
|
|
||||||
CREATE INDEX account_external_ids_byAccount
|
|
||||||
ON account_external_ids (account_id)
|
|
||||||
#
|
|
||||||
|
|
||||||
-- covers: byEmailAddress
|
|
||||||
CREATE INDEX account_external_ids_byEmail
|
|
||||||
ON account_external_ids (email_address)
|
|
||||||
#
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- AccountGroupMemberAccess
|
-- AccountGroupMemberAccess
|
||||||
-- @PrimaryKey covers: byAccount
|
-- @PrimaryKey covers: byAccount
|
||||||
|
|
|
@ -62,17 +62,6 @@ CREATE INDEX accounts_byFullName
|
||||||
ON accounts (full_name);
|
ON accounts (full_name);
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
|
||||||
-- AccountExternalIdAccess
|
|
||||||
-- covers: byAccount
|
|
||||||
CREATE INDEX account_external_ids_byAccount
|
|
||||||
ON account_external_ids (account_id);
|
|
||||||
|
|
||||||
-- covers: byEmailAddress
|
|
||||||
CREATE INDEX account_external_ids_byEmail
|
|
||||||
ON account_external_ids (email_address);
|
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- AccountGroupMemberAccess
|
-- AccountGroupMemberAccess
|
||||||
-- @PrimaryKey covers: byAccount
|
-- @PrimaryKey covers: byAccount
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class AccountByEmailCacheImpl implements AccountByEmailCache {
|
||||||
try (ReviewDb db = schema.open()) {
|
try (ReviewDb db = schema.open()) {
|
||||||
return Streams.concat(
|
return Streams.concat(
|
||||||
Streams.stream(db.accounts().byPreferredEmail(email)).map(a -> a.getId()),
|
Streams.stream(db.accounts().byPreferredEmail(email)).map(a -> a.getId()),
|
||||||
externalIds.get().byEmail(db, email).stream().map(e -> e.accountId()))
|
externalIds.get().byEmail(email).stream().map(e -> e.accountId()))
|
||||||
.collect(toImmutableSet());
|
.collect(toImmutableSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,7 @@ public class AccountCacheImpl implements AccountCache {
|
||||||
return new AccountState(
|
return new AccountState(
|
||||||
account,
|
account,
|
||||||
internalGroups,
|
internalGroups,
|
||||||
externalIds.byAccount(db, who),
|
externalIds.byAccount(who),
|
||||||
watchConfig.get().getProjectWatches(who));
|
watchConfig.get().getProjectWatches(who));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,9 +171,7 @@ public class AccountManager {
|
||||||
externalIdsUpdateFactory
|
externalIdsUpdateFactory
|
||||||
.create()
|
.create()
|
||||||
.replace(
|
.replace(
|
||||||
db,
|
extId, ExternalId.create(extId.key(), extId.accountId(), newEmail, extId.password()));
|
||||||
extId,
|
|
||||||
ExternalId.create(extId.key(), extId.accountId(), newEmail, extId.password()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!realm.allowsEdit(AccountFieldName.FULL_NAME)
|
if (!realm.allowsEdit(AccountFieldName.FULL_NAME)
|
||||||
|
@ -235,7 +233,7 @@ public class AccountManager {
|
||||||
AccountsUpdate accountsUpdate = accountsUpdateFactory.create();
|
AccountsUpdate accountsUpdate = accountsUpdateFactory.create();
|
||||||
accountsUpdate.upsert(db, account);
|
accountsUpdate.upsert(db, account);
|
||||||
|
|
||||||
ExternalId existingExtId = externalIds.get(db, extId.key());
|
ExternalId existingExtId = externalIds.get(extId.key());
|
||||||
if (existingExtId != null && !existingExtId.accountId().equals(extId.accountId())) {
|
if (existingExtId != null && !existingExtId.accountId().equals(extId.accountId())) {
|
||||||
// external ID is assigned to another account, do not overwrite
|
// external ID is assigned to another account, do not overwrite
|
||||||
accountsUpdate.delete(db, account);
|
accountsUpdate.delete(db, account);
|
||||||
|
@ -246,7 +244,7 @@ public class AccountManager {
|
||||||
+ newId
|
+ newId
|
||||||
+ "; external ID already in use.");
|
+ "; external ID already in use.");
|
||||||
}
|
}
|
||||||
externalIdsUpdateFactory.create().upsert(db, extId);
|
externalIdsUpdateFactory.create().upsert(extId);
|
||||||
} finally {
|
} finally {
|
||||||
// If adding the account failed, it may be that it actually was the
|
// If adding the account failed, it may be that it actually was the
|
||||||
// first account. So we reset the 'check for first account'-guard, as
|
// first account. So we reset the 'check for first account'-guard, as
|
||||||
|
@ -279,7 +277,7 @@ public class AccountManager {
|
||||||
//
|
//
|
||||||
IdentifiedUser user = userFactory.create(newId);
|
IdentifiedUser user = userFactory.create(newId);
|
||||||
try {
|
try {
|
||||||
changeUserNameFactory.create(db, user, who.getUserName()).call();
|
changeUserNameFactory.create(user, who.getUserName()).call();
|
||||||
} catch (NameAlreadyUsedException e) {
|
} catch (NameAlreadyUsedException e) {
|
||||||
String message =
|
String message =
|
||||||
"Cannot assign user name \""
|
"Cannot assign user name \""
|
||||||
|
@ -347,7 +345,7 @@ public class AccountManager {
|
||||||
// this is why the best we can do here is to fail early and cleanup
|
// this is why the best we can do here is to fail early and cleanup
|
||||||
// the database
|
// the database
|
||||||
accountsUpdateFactory.create().delete(db, account);
|
accountsUpdateFactory.create().delete(db, account);
|
||||||
externalIdsUpdateFactory.create().delete(db, extId);
|
externalIdsUpdateFactory.create().delete(extId);
|
||||||
throw new AccountUserNameException(errorMessage, e);
|
throw new AccountUserNameException(errorMessage, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,8 +371,7 @@ public class AccountManager {
|
||||||
} else {
|
} else {
|
||||||
externalIdsUpdateFactory
|
externalIdsUpdateFactory
|
||||||
.create()
|
.create()
|
||||||
.insert(
|
.insert(ExternalId.createWithEmail(who.getExternalIdKey(), to, who.getEmailAddress()));
|
||||||
db, ExternalId.createWithEmail(who.getExternalIdKey(), to, who.getEmailAddress()));
|
|
||||||
|
|
||||||
if (who.getEmailAddress() != null) {
|
if (who.getEmailAddress() != null) {
|
||||||
Account a = db.accounts().get(to);
|
Account a = db.accounts().get(to);
|
||||||
|
@ -409,22 +406,20 @@ public class AccountManager {
|
||||||
*/
|
*/
|
||||||
public AuthResult updateLink(Account.Id to, AuthRequest who)
|
public AuthResult updateLink(Account.Id to, AuthRequest who)
|
||||||
throws OrmException, AccountException, IOException, ConfigInvalidException {
|
throws OrmException, AccountException, IOException, ConfigInvalidException {
|
||||||
try (ReviewDb db = schema.open()) {
|
Collection<ExternalId> filteredExtIdsByScheme =
|
||||||
Collection<ExternalId> filteredExtIdsByScheme =
|
externalIds.byAccount(to, who.getExternalIdKey().scheme());
|
||||||
externalIds.byAccount(db, to, who.getExternalIdKey().scheme());
|
|
||||||
|
|
||||||
if (!filteredExtIdsByScheme.isEmpty()
|
if (!filteredExtIdsByScheme.isEmpty()
|
||||||
&& (filteredExtIdsByScheme.size() > 1
|
&& (filteredExtIdsByScheme.size() > 1
|
||||||
|| !filteredExtIdsByScheme
|
|| !filteredExtIdsByScheme
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> e.key().equals(who.getExternalIdKey()))
|
.filter(e -> e.key().equals(who.getExternalIdKey()))
|
||||||
.findAny()
|
.findAny()
|
||||||
.isPresent())) {
|
.isPresent())) {
|
||||||
externalIdsUpdateFactory.create().delete(db, filteredExtIdsByScheme);
|
externalIdsUpdateFactory.create().delete(filteredExtIdsByScheme);
|
||||||
}
|
|
||||||
byIdCache.evict(to);
|
|
||||||
return link(to, who);
|
|
||||||
}
|
}
|
||||||
|
byIdCache.evict(to);
|
||||||
|
return link(to, who);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,7 +440,7 @@ public class AccountManager {
|
||||||
throw new AccountException(
|
throw new AccountException(
|
||||||
"Identity '" + who.getExternalIdKey().get() + "' in use by another account");
|
"Identity '" + who.getExternalIdKey().get() + "' in use by another account");
|
||||||
}
|
}
|
||||||
externalIdsUpdateFactory.create().delete(db, extId);
|
externalIdsUpdateFactory.create().delete(extId);
|
||||||
|
|
||||||
if (who.getEmailAddress() != null) {
|
if (who.getEmailAddress() != null) {
|
||||||
Account a = db.accounts().get(from);
|
Account a = db.accounts().get(from);
|
||||||
|
|
|
@ -19,7 +19,6 @@ import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USE
|
||||||
import com.google.gerrit.common.Nullable;
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
import com.google.gerrit.common.errors.NameAlreadyUsedException;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
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.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIds;
|
import com.google.gerrit.server.account.externalids.ExternalIds;
|
||||||
|
@ -44,7 +43,7 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||||
|
|
||||||
/** Generic factory to change any user's username. */
|
/** Generic factory to change any user's username. */
|
||||||
public interface Factory {
|
public interface Factory {
|
||||||
ChangeUserName create(ReviewDb db, IdentifiedUser user, String newUsername);
|
ChangeUserName create(IdentifiedUser user, String newUsername);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AccountCache accountCache;
|
private final AccountCache accountCache;
|
||||||
|
@ -52,7 +51,6 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
private final ExternalIdsUpdate.Server externalIdsUpdateFactory;
|
private final ExternalIdsUpdate.Server externalIdsUpdateFactory;
|
||||||
|
|
||||||
private final ReviewDb db;
|
|
||||||
private final IdentifiedUser user;
|
private final IdentifiedUser user;
|
||||||
private final String newUsername;
|
private final String newUsername;
|
||||||
|
|
||||||
|
@ -62,14 +60,12 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||||
SshKeyCache sshKeyCache,
|
SshKeyCache sshKeyCache,
|
||||||
ExternalIds externalIds,
|
ExternalIds externalIds,
|
||||||
ExternalIdsUpdate.Server externalIdsUpdateFactory,
|
ExternalIdsUpdate.Server externalIdsUpdateFactory,
|
||||||
@Assisted ReviewDb db,
|
|
||||||
@Assisted IdentifiedUser user,
|
@Assisted IdentifiedUser user,
|
||||||
@Nullable @Assisted String newUsername) {
|
@Nullable @Assisted String newUsername) {
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
this.sshKeyCache = sshKeyCache;
|
this.sshKeyCache = sshKeyCache;
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
this.externalIdsUpdateFactory = externalIdsUpdateFactory;
|
this.externalIdsUpdateFactory = externalIdsUpdateFactory;
|
||||||
this.db = db;
|
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.newUsername = newUsername;
|
this.newUsername = newUsername;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +74,7 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||||
public VoidResult call()
|
public VoidResult call()
|
||||||
throws OrmException, NameAlreadyUsedException, InvalidUserNameException, IOException,
|
throws OrmException, NameAlreadyUsedException, InvalidUserNameException, IOException,
|
||||||
ConfigInvalidException {
|
ConfigInvalidException {
|
||||||
Collection<ExternalId> old = externalIds.byAccount(db, user.getAccountId(), SCHEME_USERNAME);
|
Collection<ExternalId> old = externalIds.byAccount(user.getAccountId(), SCHEME_USERNAME);
|
||||||
if (!old.isEmpty()) {
|
if (!old.isEmpty()) {
|
||||||
throw new IllegalStateException(USERNAME_CANNOT_BE_CHANGED);
|
throw new IllegalStateException(USERNAME_CANNOT_BE_CHANGED);
|
||||||
}
|
}
|
||||||
|
@ -97,11 +93,11 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||||
password = i.password();
|
password = i.password();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
externalIdsUpdate.insert(db, ExternalId.create(key, user.getAccountId(), null, password));
|
externalIdsUpdate.insert(ExternalId.create(key, user.getAccountId(), null, password));
|
||||||
} catch (OrmDuplicateKeyException dupeErr) {
|
} catch (OrmDuplicateKeyException dupeErr) {
|
||||||
// If we are using this identity, don't report the exception.
|
// If we are using this identity, don't report the exception.
|
||||||
//
|
//
|
||||||
ExternalId other = externalIds.get(db, key);
|
ExternalId other = externalIds.get(key);
|
||||||
if (other != null && other.accountId().equals(user.getAccountId())) {
|
if (other != null && other.accountId().equals(user.getAccountId())) {
|
||||||
return VoidResult.INSTANCE;
|
return VoidResult.INSTANCE;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +110,7 @@ public class ChangeUserName implements Callable<VoidResult> {
|
||||||
|
|
||||||
// If we have any older user names, remove them.
|
// If we have any older user names, remove them.
|
||||||
//
|
//
|
||||||
externalIdsUpdate.delete(db, old);
|
externalIdsUpdate.delete(old);
|
||||||
for (ExternalId extId : old) {
|
for (ExternalId extId : old) {
|
||||||
sshKeyCache.evict(extId.key().id());
|
sshKeyCache.evict(extId.key().id());
|
||||||
accountCache.evictByUsername(extId.key().id());
|
accountCache.evictByUsername(extId.key().id());
|
||||||
|
|
|
@ -137,11 +137,11 @@ public class CreateAccount implements RestModifyView<TopLevelResource, AccountIn
|
||||||
Account.Id id = new Account.Id(db.nextAccountId());
|
Account.Id id = new Account.Id(db.nextAccountId());
|
||||||
|
|
||||||
ExternalId extUser = ExternalId.createUsername(username, id, input.httpPassword);
|
ExternalId extUser = ExternalId.createUsername(username, id, input.httpPassword);
|
||||||
if (externalIds.get(db, extUser.key()) != null) {
|
if (externalIds.get(extUser.key()) != null) {
|
||||||
throw new ResourceConflictException("username '" + username + "' already exists");
|
throw new ResourceConflictException("username '" + username + "' already exists");
|
||||||
}
|
}
|
||||||
if (input.email != null) {
|
if (input.email != null) {
|
||||||
if (externalIds.get(db, ExternalId.Key.create(SCHEME_MAILTO, input.email)) != null) {
|
if (externalIds.get(ExternalId.Key.create(SCHEME_MAILTO, input.email)) != null) {
|
||||||
throw new UnprocessableEntityException("email '" + input.email + "' already exists");
|
throw new UnprocessableEntityException("email '" + input.email + "' already exists");
|
||||||
}
|
}
|
||||||
if (!validator.isValid(input.email)) {
|
if (!validator.isValid(input.email)) {
|
||||||
|
@ -157,17 +157,17 @@ public class CreateAccount implements RestModifyView<TopLevelResource, AccountIn
|
||||||
|
|
||||||
ExternalIdsUpdate externalIdsUpdate = externalIdsUpdateFactory.create();
|
ExternalIdsUpdate externalIdsUpdate = externalIdsUpdateFactory.create();
|
||||||
try {
|
try {
|
||||||
externalIdsUpdate.insert(db, extIds);
|
externalIdsUpdate.insert(extIds);
|
||||||
} catch (OrmDuplicateKeyException duplicateKey) {
|
} catch (OrmDuplicateKeyException duplicateKey) {
|
||||||
throw new ResourceConflictException("username '" + username + "' already exists");
|
throw new ResourceConflictException("username '" + username + "' already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.email != null) {
|
if (input.email != null) {
|
||||||
try {
|
try {
|
||||||
externalIdsUpdate.insert(db, ExternalId.createEmail(id, input.email));
|
externalIdsUpdate.insert(ExternalId.createEmail(id, input.email));
|
||||||
} catch (OrmDuplicateKeyException duplicateKey) {
|
} catch (OrmDuplicateKeyException duplicateKey) {
|
||||||
try {
|
try {
|
||||||
externalIdsUpdate.delete(db, extUser);
|
externalIdsUpdate.delete(extUser);
|
||||||
} catch (IOException | ConfigInvalidException cleanupError) {
|
} catch (IOException | ConfigInvalidException cleanupError) {
|
||||||
// Ignored
|
// Ignored
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.extensions.restapi.Response;
|
import com.google.gerrit.extensions.restapi.Response;
|
||||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.account.DeleteEmail.Input;
|
import com.google.gerrit.server.account.DeleteEmail.Input;
|
||||||
|
@ -47,7 +46,6 @@ public class DeleteEmail implements RestModifyView<AccountResource.Email, Input>
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final Realm realm;
|
private final Realm realm;
|
||||||
private final PermissionBackend permissionBackend;
|
private final PermissionBackend permissionBackend;
|
||||||
private final Provider<ReviewDb> dbProvider;
|
|
||||||
private final AccountManager accountManager;
|
private final AccountManager accountManager;
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
|
|
||||||
|
@ -56,13 +54,11 @@ public class DeleteEmail implements RestModifyView<AccountResource.Email, Input>
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
Realm realm,
|
Realm realm,
|
||||||
PermissionBackend permissionBackend,
|
PermissionBackend permissionBackend,
|
||||||
Provider<ReviewDb> dbProvider,
|
|
||||||
AccountManager accountManager,
|
AccountManager accountManager,
|
||||||
ExternalIds externalIds) {
|
ExternalIds externalIds) {
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
this.dbProvider = dbProvider;
|
|
||||||
this.accountManager = accountManager;
|
this.accountManager = accountManager;
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +83,7 @@ public class DeleteEmail implements RestModifyView<AccountResource.Email, Input>
|
||||||
|
|
||||||
Set<ExternalId> extIds =
|
Set<ExternalId> extIds =
|
||||||
externalIds
|
externalIds
|
||||||
.byAccount(dbProvider.get(), user.getAccountId())
|
.byAccount(user.getAccountId())
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> email.equals(e.email()))
|
.filter(e -> email.equals(e.email()))
|
||||||
.collect(toSet());
|
.collect(toSet());
|
||||||
|
|
|
@ -24,7 +24,6 @@ import com.google.gerrit.extensions.restapi.Response;
|
||||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIds;
|
import com.google.gerrit.server.account.externalids.ExternalIds;
|
||||||
|
@ -41,18 +40,13 @@ public class DeleteExternalIds implements RestModifyView<AccountResource, List<S
|
||||||
private final AccountManager accountManager;
|
private final AccountManager accountManager;
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final Provider<ReviewDb> dbProvider;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DeleteExternalIds(
|
DeleteExternalIds(
|
||||||
AccountManager accountManager,
|
AccountManager accountManager, ExternalIds externalIds, Provider<CurrentUser> self) {
|
||||||
ExternalIds externalIds,
|
|
||||||
Provider<CurrentUser> self,
|
|
||||||
Provider<ReviewDb> dbProvider) {
|
|
||||||
this.accountManager = accountManager;
|
this.accountManager = accountManager;
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.dbProvider = dbProvider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -68,7 +62,7 @@ public class DeleteExternalIds implements RestModifyView<AccountResource, List<S
|
||||||
|
|
||||||
Map<ExternalId.Key, ExternalId> externalIdMap =
|
Map<ExternalId.Key, ExternalId> externalIdMap =
|
||||||
externalIds
|
externalIds
|
||||||
.byAccount(dbProvider.get(), resource.getUser().getAccountId())
|
.byAccount(resource.getUser().getAccountId())
|
||||||
.stream()
|
.stream()
|
||||||
.collect(toMap(i -> i.key(), i -> i));
|
.collect(toMap(i -> i.key(), i -> i));
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.google.gerrit.extensions.common.AccountExternalIdInfo;
|
||||||
import com.google.gerrit.extensions.restapi.AuthException;
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIds;
|
import com.google.gerrit.server.account.externalids.ExternalIds;
|
||||||
|
@ -38,18 +37,12 @@ import java.util.List;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class GetExternalIds implements RestReadView<AccountResource> {
|
public class GetExternalIds implements RestReadView<AccountResource> {
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final AuthConfig authConfig;
|
private final AuthConfig authConfig;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetExternalIds(
|
GetExternalIds(ExternalIds externalIds, Provider<CurrentUser> self, AuthConfig authConfig) {
|
||||||
Provider<ReviewDb> db,
|
|
||||||
ExternalIds externalIds,
|
|
||||||
Provider<CurrentUser> self,
|
|
||||||
AuthConfig authConfig) {
|
|
||||||
this.db = db;
|
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.authConfig = authConfig;
|
this.authConfig = authConfig;
|
||||||
|
@ -62,7 +55,7 @@ public class GetExternalIds implements RestReadView<AccountResource> {
|
||||||
throw new AuthException("not allowed to get external IDs");
|
throw new AuthException("not allowed to get external IDs");
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<ExternalId> ids = externalIds.byAccount(db.get(), resource.getUser().getAccountId());
|
Collection<ExternalId> ids = externalIds.byAccount(resource.getUser().getAccountId());
|
||||||
if (ids.isEmpty()) {
|
if (ids.isEmpty()) {
|
||||||
return ImmutableList.of();
|
return ImmutableList.of();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.extensions.restapi.Response;
|
import com.google.gerrit.extensions.restapi.Response;
|
||||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.account.PutHttpPassword.Input;
|
import com.google.gerrit.server.account.PutHttpPassword.Input;
|
||||||
|
@ -59,7 +58,6 @@ public class PutHttpPassword implements RestModifyView<AccountResource, Input> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final Provider<ReviewDb> dbProvider;
|
|
||||||
private final PermissionBackend permissionBackend;
|
private final PermissionBackend permissionBackend;
|
||||||
private final AccountCache accountCache;
|
private final AccountCache accountCache;
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
|
@ -68,13 +66,11 @@ public class PutHttpPassword implements RestModifyView<AccountResource, Input> {
|
||||||
@Inject
|
@Inject
|
||||||
PutHttpPassword(
|
PutHttpPassword(
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
Provider<ReviewDb> dbProvider,
|
|
||||||
PermissionBackend permissionBackend,
|
PermissionBackend permissionBackend,
|
||||||
AccountCache accountCache,
|
AccountCache accountCache,
|
||||||
ExternalIds externalIds,
|
ExternalIds externalIds,
|
||||||
ExternalIdsUpdate.User externalIdsUpdate) {
|
ExternalIdsUpdate.User externalIdsUpdate) {
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.dbProvider = dbProvider;
|
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
this.accountCache = accountCache;
|
this.accountCache = accountCache;
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
|
@ -114,15 +110,13 @@ public class PutHttpPassword implements RestModifyView<AccountResource, Input> {
|
||||||
throw new ResourceConflictException("username must be set");
|
throw new ResourceConflictException("username must be set");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalId extId =
|
ExternalId extId = externalIds.get(ExternalId.Key.create(SCHEME_USERNAME, user.getUserName()));
|
||||||
externalIds.get(
|
|
||||||
dbProvider.get(), ExternalId.Key.create(SCHEME_USERNAME, user.getUserName()));
|
|
||||||
if (extId == null) {
|
if (extId == null) {
|
||||||
throw new ResourceNotFoundException();
|
throw new ResourceNotFoundException();
|
||||||
}
|
}
|
||||||
ExternalId newExtId =
|
ExternalId newExtId =
|
||||||
ExternalId.createWithPassword(extId.key(), extId.accountId(), extId.email(), newPassword);
|
ExternalId.createWithPassword(extId.key(), extId.accountId(), extId.email(), newPassword);
|
||||||
externalIdsUpdate.create().upsert(dbProvider.get(), newExtId);
|
externalIdsUpdate.create().upsert(newExtId);
|
||||||
accountCache.evict(user.getAccountId());
|
accountCache.evict(user.getAccountId());
|
||||||
|
|
||||||
return Strings.isNullOrEmpty(newPassword) ? Response.<String>none() : Response.ok(newPassword);
|
return Strings.isNullOrEmpty(newPassword) ? Response.<String>none() : Response.ok(newPassword);
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.PutUsername.Input;
|
import com.google.gerrit.server.account.PutUsername.Input;
|
||||||
import com.google.gerrit.server.permissions.GlobalPermission;
|
import com.google.gerrit.server.permissions.GlobalPermission;
|
||||||
|
@ -45,20 +44,17 @@ public class PutUsername implements RestModifyView<AccountResource, Input> {
|
||||||
private final ChangeUserName.Factory changeUserNameFactory;
|
private final ChangeUserName.Factory changeUserNameFactory;
|
||||||
private final PermissionBackend permissionBackend;
|
private final PermissionBackend permissionBackend;
|
||||||
private final Realm realm;
|
private final Realm realm;
|
||||||
private final Provider<ReviewDb> db;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PutUsername(
|
PutUsername(
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
ChangeUserName.Factory changeUserNameFactory,
|
ChangeUserName.Factory changeUserNameFactory,
|
||||||
PermissionBackend permissionBackend,
|
PermissionBackend permissionBackend,
|
||||||
Realm realm,
|
Realm realm) {
|
||||||
Provider<ReviewDb> db) {
|
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.changeUserNameFactory = changeUserNameFactory;
|
this.changeUserNameFactory = changeUserNameFactory;
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.db = db;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,7 +75,7 @@ public class PutUsername implements RestModifyView<AccountResource, Input> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
changeUserNameFactory.create(db.get(), rsrc.getUser(), input.username).call();
|
changeUserNameFactory.create(rsrc.getUser(), input.username).call();
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
if (ChangeUserName.USERNAME_CANNOT_BE_CHANGED.equals(e.getMessage())) {
|
if (ChangeUserName.USERNAME_CANNOT_BE_CHANGED.equals(e.getMessage())) {
|
||||||
throw new MethodNotAllowedException(e.getMessage());
|
throw new MethodNotAllowedException(e.getMessage());
|
||||||
|
|
|
@ -16,20 +16,16 @@ package com.google.gerrit.server.account.externalids;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static java.util.stream.Collectors.toSet;
|
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import com.google.gerrit.common.Nullable;
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.extensions.client.AuthType;
|
import com.google.gerrit.extensions.client.AuthType;
|
||||||
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.server.account.HashedPassword;
|
import com.google.gerrit.server.account.HashedPassword;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
@ -75,10 +71,6 @@ public abstract class ExternalId implements Serializable {
|
||||||
return new AutoValue_ExternalId_Key(Strings.emptyToNull(scheme), id);
|
return new AutoValue_ExternalId_Key(Strings.emptyToNull(scheme), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExternalId.Key from(AccountExternalId.Key externalIdKey) {
|
|
||||||
return parse(externalIdKey.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an external ID key from a string in the format "scheme:id" or "id".
|
* Parses an external ID key from a string in the format "scheme:id" or "id".
|
||||||
*
|
*
|
||||||
|
@ -92,11 +84,6 @@ public abstract class ExternalId implements Serializable {
|
||||||
return create(externalId.substring(0, c), externalId.substring(c + 1));
|
return create(externalId.substring(0, c), externalId.substring(c + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<AccountExternalId.Key> toAccountExternalIdKeys(
|
|
||||||
Collection<ExternalId.Key> extIdKeys) {
|
|
||||||
return extIdKeys.stream().map(k -> k.asAccountExternalIdKey()).collect(toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract @Nullable String scheme();
|
public abstract @Nullable String scheme();
|
||||||
|
|
||||||
public abstract String id();
|
public abstract String id();
|
||||||
|
@ -105,13 +92,6 @@ public abstract class ExternalId implements Serializable {
|
||||||
return scheme.equals(scheme());
|
return scheme.equals(scheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountExternalId.Key asAccountExternalIdKey() {
|
|
||||||
if (scheme() != null) {
|
|
||||||
return new AccountExternalId.Key(scheme(), id());
|
|
||||||
}
|
|
||||||
return new AccountExternalId.Key(id());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SHA1 of the external ID that is used as note ID in the refs/meta/external-ids
|
* Returns the SHA1 of the external ID that is used as note ID in the refs/meta/external-ids
|
||||||
* notes branch.
|
* notes branch.
|
||||||
|
@ -281,29 +261,6 @@ public abstract class ExternalId implements Serializable {
|
||||||
String.format("Invalid external ID config for note '%s': %s", noteId, message));
|
String.format("Invalid external ID config for note '%s': %s", noteId, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExternalId from(AccountExternalId externalId) {
|
|
||||||
if (externalId == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new AutoValue_ExternalId(
|
|
||||||
ExternalId.Key.parse(externalId.getExternalId()),
|
|
||||||
externalId.getAccountId(),
|
|
||||||
Strings.emptyToNull(externalId.getEmailAddress()),
|
|
||||||
Strings.emptyToNull(externalId.getPassword()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<ExternalId> from(Collection<AccountExternalId> externalIds) {
|
|
||||||
if (externalIds == null) {
|
|
||||||
return ImmutableSet.of();
|
|
||||||
}
|
|
||||||
return externalIds.stream().map(ExternalId::from).collect(toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<AccountExternalId> toAccountExternalIds(Collection<ExternalId> extIds) {
|
|
||||||
return extIds.stream().map(e -> e.asAccountExternalId()).collect(toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Key key();
|
public abstract Key key();
|
||||||
|
|
||||||
public abstract Account.Id accountId();
|
public abstract Account.Id accountId();
|
||||||
|
@ -316,13 +273,6 @@ public abstract class ExternalId implements Serializable {
|
||||||
return key().isScheme(scheme);
|
return key().isScheme(scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountExternalId asAccountExternalId() {
|
|
||||||
AccountExternalId extId = new AccountExternalId(accountId(), key().asAccountExternalIdKey());
|
|
||||||
extId.setEmailAddress(email());
|
|
||||||
extId.setPassword(password());
|
|
||||||
return extId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports this external ID as Git config file text.
|
* Exports this external ID as Git config file text.
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,18 +24,14 @@ 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.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.config.AllUsersName;
|
import com.google.gerrit.server.config.AllUsersName;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
import com.google.gwtorm.server.OrmException;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
import org.eclipse.jgit.lib.Config;
|
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
@ -46,7 +42,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to read external IDs from ReviewDb or NoteDb.
|
* Class to read external IDs from NoteDb.
|
||||||
*
|
*
|
||||||
* <p>In NoteDb external IDs are stored in the All-Users repository in a Git Notes branch called
|
* <p>In NoteDb external IDs are stored in the All-Users repository in a Git Notes branch called
|
||||||
* refs/meta/external-ids where the sha1 of the external ID is used as note name. Each note content
|
* refs/meta/external-ids where the sha1 of the external ID is used as note name. Each note content
|
||||||
|
@ -78,7 +74,6 @@ public class ExternalIdReader {
|
||||||
return NoteMap.newEmptyMap();
|
return NoteMap.newEmptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean readFromGit;
|
|
||||||
private final GitRepositoryManager repoManager;
|
private final GitRepositoryManager repoManager;
|
||||||
private final AllUsersName allUsersName;
|
private final AllUsersName allUsersName;
|
||||||
private boolean failOnLoad = false;
|
private boolean failOnLoad = false;
|
||||||
|
@ -86,11 +81,7 @@ public class ExternalIdReader {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ExternalIdReader(
|
ExternalIdReader(
|
||||||
@GerritServerConfig Config cfg,
|
GitRepositoryManager repoManager, AllUsersName allUsersName, MetricMaker metricMaker) {
|
||||||
GitRepositoryManager repoManager,
|
|
||||||
AllUsersName allUsersName,
|
|
||||||
MetricMaker metricMaker) {
|
|
||||||
this.readFromGit = cfg.getBoolean("user", null, "readExternalIdsFromGit", false);
|
|
||||||
this.repoManager = repoManager;
|
this.repoManager = repoManager;
|
||||||
this.allUsersName = allUsersName;
|
this.allUsersName = allUsersName;
|
||||||
this.readAllLatency =
|
this.readAllLatency =
|
||||||
|
@ -106,10 +97,6 @@ public class ExternalIdReader {
|
||||||
this.failOnLoad = failOnLoad;
|
this.failOnLoad = failOnLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean readFromGit() {
|
|
||||||
return readFromGit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectId readRevision() throws IOException {
|
ObjectId readRevision() throws IOException {
|
||||||
try (Repository repo = repoManager.openRepository(allUsersName)) {
|
try (Repository repo = repoManager.openRepository(allUsersName)) {
|
||||||
return readRevision(repo);
|
return readRevision(repo);
|
||||||
|
@ -117,16 +104,12 @@ public class ExternalIdReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reads and returns all external IDs. */
|
/** Reads and returns all external IDs. */
|
||||||
Set<ExternalId> all(ReviewDb db) throws IOException, OrmException {
|
Set<ExternalId> all() throws IOException {
|
||||||
checkReadEnabled();
|
checkReadEnabled();
|
||||||
|
|
||||||
if (readFromGit) {
|
try (Repository repo = repoManager.openRepository(allUsersName)) {
|
||||||
try (Repository repo = repoManager.openRepository(allUsersName)) {
|
return all(repo, readRevision(repo));
|
||||||
return all(repo, readRevision(repo));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExternalId.from(db.accountExternalIds().all().toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,22 +149,18 @@ public class ExternalIdReader {
|
||||||
|
|
||||||
/** Reads and returns the specified external ID. */
|
/** Reads and returns the specified external ID. */
|
||||||
@Nullable
|
@Nullable
|
||||||
ExternalId get(ReviewDb db, ExternalId.Key key)
|
ExternalId get(ExternalId.Key key) throws IOException, ConfigInvalidException {
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
|
||||||
checkReadEnabled();
|
checkReadEnabled();
|
||||||
|
|
||||||
if (readFromGit) {
|
try (Repository repo = repoManager.openRepository(allUsersName);
|
||||||
try (Repository repo = repoManager.openRepository(allUsersName);
|
RevWalk rw = new RevWalk(repo)) {
|
||||||
RevWalk rw = new RevWalk(repo)) {
|
ObjectId rev = readRevision(repo);
|
||||||
ObjectId rev = readRevision(repo);
|
if (rev.equals(ObjectId.zeroId())) {
|
||||||
if (rev.equals(ObjectId.zeroId())) {
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return parse(key, rw, rev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return parse(key, rw, rev);
|
||||||
}
|
}
|
||||||
return ExternalId.from(db.accountExternalIds().get(key.asAccountExternalIdKey()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reads and returns the specified external ID from the given revision. */
|
/** Reads and returns the specified external ID from the given revision. */
|
||||||
|
|
|
@ -18,8 +18,6 @@ import static java.util.stream.Collectors.toSet;
|
||||||
|
|
||||||
import com.google.gerrit.common.Nullable;
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -44,8 +42,8 @@ public class ExternalIds {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns all external IDs. */
|
/** Returns all external IDs. */
|
||||||
public Set<ExternalId> all(ReviewDb db) throws IOException, OrmException {
|
public Set<ExternalId> all() throws IOException {
|
||||||
return externalIdReader.all(db);
|
return externalIdReader.all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns all external IDs from the specified revision of the refs/meta/external-ids branch. */
|
/** Returns all external IDs from the specified revision of the refs/meta/external-ids branch. */
|
||||||
|
@ -55,9 +53,8 @@ public class ExternalIds {
|
||||||
|
|
||||||
/** Returns the specified external ID. */
|
/** Returns the specified external ID. */
|
||||||
@Nullable
|
@Nullable
|
||||||
public ExternalId get(ReviewDb db, ExternalId.Key key)
|
public ExternalId get(ExternalId.Key key) throws IOException, ConfigInvalidException {
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
return externalIdReader.get(key);
|
||||||
return externalIdReader.get(db, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the specified external ID from the given revision. */
|
/** Returns the specified external ID from the given revision. */
|
||||||
|
@ -68,26 +65,16 @@ public class ExternalIds {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the external IDs of the specified account. */
|
/** Returns the external IDs of the specified account. */
|
||||||
public Set<ExternalId> byAccount(ReviewDb db, Account.Id accountId)
|
public Set<ExternalId> byAccount(Account.Id accountId) throws IOException {
|
||||||
throws IOException, OrmException {
|
return externalIdCache.byAccount(accountId);
|
||||||
if (externalIdReader.readFromGit()) {
|
|
||||||
return externalIdCache.byAccount(accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExternalId.from(db.accountExternalIds().byAccount(accountId).toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the external IDs of the specified account that have the given scheme. */
|
/** Returns the external IDs of the specified account that have the given scheme. */
|
||||||
public Set<ExternalId> byAccount(ReviewDb db, Account.Id accountId, String scheme)
|
public Set<ExternalId> byAccount(Account.Id accountId, String scheme) throws IOException {
|
||||||
throws IOException, OrmException {
|
return byAccount(accountId).stream().filter(e -> e.key().isScheme(scheme)).collect(toSet());
|
||||||
return byAccount(db, accountId).stream().filter(e -> e.key().isScheme(scheme)).collect(toSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ExternalId> byEmail(ReviewDb db, String email) throws IOException, OrmException {
|
public Set<ExternalId> byEmail(String email) throws IOException {
|
||||||
if (externalIdReader.readFromGit()) {
|
return externalIdCache.byEmail(email);
|
||||||
return externalIdCache.byEmail(email);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExternalId.from(db.accountExternalIds().byEmailAddress(email).toList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,7 @@
|
||||||
|
|
||||||
package com.google.gerrit.server.account.externalids;
|
package com.google.gerrit.server.account.externalids;
|
||||||
|
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalId.toAccountExternalIds;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.config.AllUsersName;
|
import com.google.gerrit.server.config.AllUsersName;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
@ -39,8 +36,8 @@ import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
*
|
*
|
||||||
* <p>For NoteDb all updates will result in a single commit to the refs/meta/external-ids branch.
|
* <p>For NoteDb all updates will result in a single commit to the refs/meta/external-ids branch.
|
||||||
* This means callers can prepare many updates by invoking {@link #replace(ExternalId, ExternalId)}
|
* This means callers can prepare many updates by invoking {@link #replace(ExternalId, ExternalId)}
|
||||||
* multiple times and when {@link ExternalIdsBatchUpdate#commit(ReviewDb, String)} is invoked a
|
* multiple times and when {@link ExternalIdsBatchUpdate#commit(String)} is invoked a single NoteDb
|
||||||
* single NoteDb commit is created that contains all the prepared updates.
|
* commit is created that contains all the prepared updates.
|
||||||
*/
|
*/
|
||||||
public class ExternalIdsBatchUpdate {
|
public class ExternalIdsBatchUpdate {
|
||||||
private final GitRepositoryManager repoManager;
|
private final GitRepositoryManager repoManager;
|
||||||
|
@ -65,7 +62,7 @@ public class ExternalIdsBatchUpdate {
|
||||||
/**
|
/**
|
||||||
* Adds an external ID replacement to the batch.
|
* Adds an external ID replacement to the batch.
|
||||||
*
|
*
|
||||||
* <p>The actual replacement is only done when {@link #commit(ReviewDb, String)} is invoked.
|
* <p>The actual replacement is only done when {@link #commit(String)} is invoked.
|
||||||
*/
|
*/
|
||||||
public void replace(ExternalId extIdToDelete, ExternalId extIdToAdd) {
|
public void replace(ExternalId extIdToDelete, ExternalId extIdToAdd) {
|
||||||
ExternalIdsUpdate.checkSameAccount(ImmutableSet.of(extIdToDelete, extIdToAdd));
|
ExternalIdsUpdate.checkSameAccount(ImmutableSet.of(extIdToDelete, extIdToAdd));
|
||||||
|
@ -85,15 +82,12 @@ public class ExternalIdsBatchUpdate {
|
||||||
*
|
*
|
||||||
* <p>For NoteDb a single commit is created that contains all the external ID updates.
|
* <p>For NoteDb a single commit is created that contains all the external ID updates.
|
||||||
*/
|
*/
|
||||||
public void commit(ReviewDb db, String commitMessage)
|
public void commit(String commitMessage)
|
||||||
throws IOException, OrmException, ConfigInvalidException {
|
throws IOException, OrmException, ConfigInvalidException {
|
||||||
if (toDelete.isEmpty() && toAdd.isEmpty()) {
|
if (toDelete.isEmpty() && toAdd.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.accountExternalIds().delete(toAccountExternalIds(toDelete));
|
|
||||||
db.accountExternalIds().insert(toAccountExternalIds(toAdd));
|
|
||||||
|
|
||||||
try (Repository repo = repoManager.openRepository(allUsersName);
|
try (Repository repo = repoManager.openRepository(allUsersName);
|
||||||
RevWalk rw = new RevWalk(repo);
|
RevWalk rw = new RevWalk(repo);
|
||||||
ObjectInserter ins = repo.newObjectInserter()) {
|
ObjectInserter ins = repo.newObjectInserter()) {
|
||||||
|
|
|
@ -16,8 +16,6 @@ package com.google.gerrit.server.account.externalids;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalId.Key.toAccountExternalIdKeys;
|
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalId.toAccountExternalIds;
|
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalIdReader.MAX_NOTE_SZ;
|
import static com.google.gerrit.server.account.externalids.ExternalIdReader.MAX_NOTE_SZ;
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalIdReader.readNoteMap;
|
import static com.google.gerrit.server.account.externalids.ExternalIdReader.readNoteMap;
|
||||||
import static com.google.gerrit.server.account.externalids.ExternalIdReader.readRevision;
|
import static com.google.gerrit.server.account.externalids.ExternalIdReader.readRevision;
|
||||||
|
@ -42,7 +40,6 @@ import com.google.gerrit.metrics.Description;
|
||||||
import com.google.gerrit.metrics.MetricMaker;
|
import com.google.gerrit.metrics.MetricMaker;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.config.AllUsersName;
|
import com.google.gerrit.server.config.AllUsersName;
|
||||||
|
@ -252,9 +249,8 @@ public class ExternalIdsUpdate {
|
||||||
*
|
*
|
||||||
* <p>If the external ID already exists, the insert fails with {@link OrmDuplicateKeyException}.
|
* <p>If the external ID already exists, the insert fails with {@link OrmDuplicateKeyException}.
|
||||||
*/
|
*/
|
||||||
public void insert(ReviewDb db, ExternalId extId)
|
public void insert(ExternalId extId) throws IOException, ConfigInvalidException, OrmException {
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
insert(Collections.singleton(extId));
|
||||||
insert(db, Collections.singleton(extId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,10 +259,8 @@ public class ExternalIdsUpdate {
|
||||||
* <p>If any of the external ID already exists, the insert fails with {@link
|
* <p>If any of the external ID already exists, the insert fails with {@link
|
||||||
* OrmDuplicateKeyException}.
|
* OrmDuplicateKeyException}.
|
||||||
*/
|
*/
|
||||||
public void insert(ReviewDb db, Collection<ExternalId> extIds)
|
public void insert(Collection<ExternalId> extIds)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
db.accountExternalIds().insert(toAccountExternalIds(extIds));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -282,9 +276,8 @@ public class ExternalIdsUpdate {
|
||||||
*
|
*
|
||||||
* <p>If the external ID already exists, it is overwritten, otherwise it is inserted.
|
* <p>If the external ID already exists, it is overwritten, otherwise it is inserted.
|
||||||
*/
|
*/
|
||||||
public void upsert(ReviewDb db, ExternalId extId)
|
public void upsert(ExternalId extId) throws IOException, ConfigInvalidException, OrmException {
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
upsert(Collections.singleton(extId));
|
||||||
upsert(db, Collections.singleton(extId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,10 +285,8 @@ public class ExternalIdsUpdate {
|
||||||
*
|
*
|
||||||
* <p>If any of the external IDs already exists, it is overwritten. New external IDs are inserted.
|
* <p>If any of the external IDs already exists, it is overwritten. New external IDs are inserted.
|
||||||
*/
|
*/
|
||||||
public void upsert(ReviewDb db, Collection<ExternalId> extIds)
|
public void upsert(Collection<ExternalId> extIds)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
db.accountExternalIds().upsert(toAccountExternalIds(extIds));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -312,9 +303,8 @@ public class ExternalIdsUpdate {
|
||||||
* @throws IllegalStateException is thrown if there is an existing external ID that has the same
|
* @throws IllegalStateException is thrown if there is an existing external ID that has the same
|
||||||
* key, but otherwise doesn't match the specified external ID.
|
* key, but otherwise doesn't match the specified external ID.
|
||||||
*/
|
*/
|
||||||
public void delete(ReviewDb db, ExternalId extId)
|
public void delete(ExternalId extId) throws IOException, ConfigInvalidException, OrmException {
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
delete(Collections.singleton(extId));
|
||||||
delete(db, Collections.singleton(extId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -324,10 +314,8 @@ public class ExternalIdsUpdate {
|
||||||
* key as any of the external IDs that should be deleted, but otherwise doesn't match the that
|
* key as any of the external IDs that should be deleted, but otherwise doesn't match the that
|
||||||
* external ID.
|
* external ID.
|
||||||
*/
|
*/
|
||||||
public void delete(ReviewDb db, Collection<ExternalId> extIds)
|
public void delete(Collection<ExternalId> extIds)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
db.accountExternalIds().delete(toAccountExternalIds(extIds));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -344,9 +332,9 @@ public class ExternalIdsUpdate {
|
||||||
* @throws IllegalStateException is thrown if the external ID does not belong to the specified
|
* @throws IllegalStateException is thrown if the external ID does not belong to the specified
|
||||||
* account.
|
* account.
|
||||||
*/
|
*/
|
||||||
public void delete(ReviewDb db, Account.Id accountId, ExternalId.Key extIdKey)
|
public void delete(Account.Id accountId, ExternalId.Key extIdKey)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
delete(db, accountId, Collections.singleton(extIdKey));
|
delete(accountId, Collections.singleton(extIdKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -355,10 +343,8 @@ public class ExternalIdsUpdate {
|
||||||
* @throws IllegalStateException is thrown if any of the external IDs does not belong to the
|
* @throws IllegalStateException is thrown if any of the external IDs does not belong to the
|
||||||
* specified account.
|
* specified account.
|
||||||
*/
|
*/
|
||||||
public void delete(ReviewDb db, Account.Id accountId, Collection<ExternalId.Key> extIdKeys)
|
public void delete(Account.Id accountId, Collection<ExternalId.Key> extIdKeys)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
db.accountExternalIds().deleteKeys(toAccountExternalIdKeys(extIdKeys));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -374,10 +360,8 @@ public class ExternalIdsUpdate {
|
||||||
*
|
*
|
||||||
* <p>The external IDs are deleted regardless of which account they belong to.
|
* <p>The external IDs are deleted regardless of which account they belong to.
|
||||||
*/
|
*/
|
||||||
public void deleteByKeys(ReviewDb db, Collection<ExternalId.Key> extIdKeys)
|
public void deleteByKeys(Collection<ExternalId.Key> extIdKeys)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
db.accountExternalIds().deleteKeys(toAccountExternalIdKeys(extIdKeys));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -389,9 +373,9 @@ public class ExternalIdsUpdate {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deletes all external IDs of the specified account. */
|
/** Deletes all external IDs of the specified account. */
|
||||||
public void deleteAll(ReviewDb db, Account.Id accountId)
|
public void deleteAll(Account.Id accountId)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
delete(db, externalIds.byAccount(db, accountId));
|
delete(externalIds.byAccount(accountId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -406,16 +390,10 @@ public class ExternalIdsUpdate {
|
||||||
* the specified account.
|
* the specified account.
|
||||||
*/
|
*/
|
||||||
public void replace(
|
public void replace(
|
||||||
ReviewDb db,
|
Account.Id accountId, Collection<ExternalId.Key> toDelete, Collection<ExternalId> toAdd)
|
||||||
Account.Id accountId,
|
|
||||||
Collection<ExternalId.Key> toDelete,
|
|
||||||
Collection<ExternalId> toAdd)
|
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
checkSameAccount(toAdd, accountId);
|
checkSameAccount(toAdd, accountId);
|
||||||
|
|
||||||
db.accountExternalIds().deleteKeys(toAccountExternalIdKeys(toDelete));
|
|
||||||
db.accountExternalIds().insert(toAccountExternalIds(toAdd));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -440,12 +418,8 @@ public class ExternalIdsUpdate {
|
||||||
*
|
*
|
||||||
* <p>The external IDs are replaced regardless of which account they belong to.
|
* <p>The external IDs are replaced regardless of which account they belong to.
|
||||||
*/
|
*/
|
||||||
public void replaceByKeys(
|
public void replaceByKeys(Collection<ExternalId.Key> toDelete, Collection<ExternalId> toAdd)
|
||||||
ReviewDb db, Collection<ExternalId.Key> toDelete, Collection<ExternalId> toAdd)
|
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
db.accountExternalIds().deleteKeys(toAccountExternalIdKeys(toDelete));
|
|
||||||
db.accountExternalIds().insert(toAccountExternalIds(toAdd));
|
|
||||||
|
|
||||||
RefsMetaExternalIdsUpdate u =
|
RefsMetaExternalIdsUpdate u =
|
||||||
updateNoteMap(
|
updateNoteMap(
|
||||||
o -> {
|
o -> {
|
||||||
|
@ -466,9 +440,9 @@ public class ExternalIdsUpdate {
|
||||||
* @throws IllegalStateException is thrown if the specified external IDs belong to different
|
* @throws IllegalStateException is thrown if the specified external IDs belong to different
|
||||||
* accounts.
|
* accounts.
|
||||||
*/
|
*/
|
||||||
public void replace(ReviewDb db, ExternalId toDelete, ExternalId toAdd)
|
public void replace(ExternalId toDelete, ExternalId toAdd)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
replace(db, Collections.singleton(toDelete), Collections.singleton(toAdd));
|
replace(Collections.singleton(toDelete), Collections.singleton(toAdd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -482,7 +456,7 @@ public class ExternalIdsUpdate {
|
||||||
* @throws IllegalStateException is thrown if the specified external IDs belong to different
|
* @throws IllegalStateException is thrown if the specified external IDs belong to different
|
||||||
* accounts.
|
* accounts.
|
||||||
*/
|
*/
|
||||||
public void replace(ReviewDb db, Collection<ExternalId> toDelete, Collection<ExternalId> toAdd)
|
public void replace(Collection<ExternalId> toDelete, Collection<ExternalId> toAdd)
|
||||||
throws IOException, ConfigInvalidException, OrmException {
|
throws IOException, ConfigInvalidException, OrmException {
|
||||||
Account.Id accountId = checkSameAccount(Iterables.concat(toDelete, toAdd));
|
Account.Id accountId = checkSameAccount(Iterables.concat(toDelete, toAdd));
|
||||||
if (accountId == null) {
|
if (accountId == null) {
|
||||||
|
@ -490,7 +464,7 @@ public class ExternalIdsUpdate {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
replace(db, accountId, toDelete.stream().map(e -> e.key()).collect(toSet()), toAdd);
|
replace(accountId, toDelete.stream().map(e -> e.key()).collect(toSet()), toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,7 +25,6 @@ import com.google.gerrit.extensions.client.AccountFieldName;
|
||||||
import com.google.gerrit.extensions.client.AuthType;
|
import com.google.gerrit.extensions.client.AuthType;
|
||||||
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.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.account.AbstractRealm;
|
import com.google.gerrit.server.account.AbstractRealm;
|
||||||
import com.google.gerrit.server.account.AccountException;
|
import com.google.gerrit.server.account.AccountException;
|
||||||
import com.google.gerrit.server.account.AuthRequest;
|
import com.google.gerrit.server.account.AuthRequest;
|
||||||
|
@ -36,7 +35,6 @@ import com.google.gerrit.server.account.externalids.ExternalIds;
|
||||||
import com.google.gerrit.server.auth.AuthenticationUnavailableException;
|
import com.google.gerrit.server.auth.AuthenticationUnavailableException;
|
||||||
import com.google.gerrit.server.config.AuthConfig;
|
import com.google.gerrit.server.config.AuthConfig;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
@ -319,22 +317,17 @@ class LdapRealm extends AbstractRealm {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class UserLoader extends CacheLoader<String, Optional<Account.Id>> {
|
static class UserLoader extends CacheLoader<String, Optional<Account.Id>> {
|
||||||
private final SchemaFactory<ReviewDb> schema;
|
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UserLoader(SchemaFactory<ReviewDb> schema, ExternalIds externalIds) {
|
UserLoader(ExternalIds externalIds) {
|
||||||
this.schema = schema;
|
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Account.Id> load(String username) throws Exception {
|
public Optional<Account.Id> load(String username) throws Exception {
|
||||||
try (ReviewDb db = schema.open()) {
|
return Optional.ofNullable(externalIds.get(ExternalId.Key.create(SCHEME_GERRIT, username)))
|
||||||
return Optional.ofNullable(
|
.map(ExternalId::accountId);
|
||||||
externalIds.get(db, ExternalId.Key.create(SCHEME_GERRIT, username)))
|
|
||||||
.map(ExternalId::accountId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
/** A version of the database schema. */
|
/** A version of the database schema. */
|
||||||
public abstract class SchemaVersion {
|
public abstract class SchemaVersion {
|
||||||
/** The current schema version. */
|
/** The current schema version. */
|
||||||
public static final Class<Schema_149> C = Schema_149.class;
|
public static final Class<Schema_150> C = Schema_150.class;
|
||||||
|
|
||||||
public static int getBinaryVersion() {
|
public static int getBinaryVersion() {
|
||||||
return guessVersion(C);
|
return guessVersion(C);
|
||||||
|
|
|
@ -14,16 +14,24 @@
|
||||||
|
|
||||||
package com.google.gerrit.server.schema;
|
package com.google.gerrit.server.schema;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.AccountExternalId;
|
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.account.HashedPassword;
|
import com.google.gerrit.server.account.HashedPassword;
|
||||||
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
|
import com.google.gwtorm.jdbc.JdbcSchema;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.sql.Statement;
|
||||||
|
|
||||||
public class Schema_142 extends SchemaVersion {
|
public class Schema_142 extends SchemaVersion {
|
||||||
|
private static final int MAX_BATCH_SIZE = 1000;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Schema_142(Provider<Schema_141> prior) {
|
Schema_142(Provider<Schema_141> prior) {
|
||||||
super(prior);
|
super(prior);
|
||||||
|
@ -31,19 +39,39 @@ public class Schema_142 extends SchemaVersion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
|
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
|
||||||
List<AccountExternalId> newIds = db.accountExternalIds().all().toList();
|
try (PreparedStatement updateStmt =
|
||||||
for (AccountExternalId id : newIds) {
|
((JdbcSchema) db)
|
||||||
if (!id.isScheme(AccountExternalId.SCHEME_USERNAME)) {
|
.getConnection()
|
||||||
continue;
|
.prepareStatement(
|
||||||
|
"UPDATE account_external_ids " + "SET password = ? " + "WHERE external_id = ?")) {
|
||||||
|
int batchCount = 0;
|
||||||
|
|
||||||
|
try (Statement stmt = newStatement(db);
|
||||||
|
ResultSet rs =
|
||||||
|
stmt.executeQuery("SELECT external_id, password FROM account_external_ids")) {
|
||||||
|
while (rs.next()) {
|
||||||
|
String externalId = rs.getString("external_id");
|
||||||
|
String password = rs.getString("password");
|
||||||
|
if (!ExternalId.Key.parse(externalId).isScheme(SCHEME_USERNAME)
|
||||||
|
|| Strings.isNullOrEmpty(password)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashedPassword hashed = HashedPassword.fromPassword(password);
|
||||||
|
updateStmt.setString(1, hashed.encode());
|
||||||
|
updateStmt.setString(2, externalId);
|
||||||
|
updateStmt.addBatch();
|
||||||
|
batchCount++;
|
||||||
|
if (batchCount >= MAX_BATCH_SIZE) {
|
||||||
|
updateStmt.executeBatch();
|
||||||
|
batchCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String password = id.getPassword();
|
if (batchCount > 0) {
|
||||||
if (password != null) {
|
updateStmt.executeBatch();
|
||||||
HashedPassword hashed = HashedPassword.fromPassword(password);
|
|
||||||
id.setPassword(hashed.encode());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.accountExternalIds().upsert(newIds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
package com.google.gerrit.server.schema;
|
package com.google.gerrit.server.schema;
|
||||||
|
|
||||||
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
|
@ -21,11 +22,15 @@ import com.google.gerrit.server.account.externalids.ExternalIdReader;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIdsUpdate;
|
import com.google.gerrit.server.account.externalids.ExternalIdsUpdate;
|
||||||
import com.google.gerrit.server.config.AllUsersName;
|
import com.google.gerrit.server.config.AllUsersName;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gwtorm.jdbc.JdbcSchema;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
@ -56,7 +61,26 @@ public class Schema_144 extends SchemaVersion {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
|
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
|
||||||
Set<ExternalId> toAdd = ExternalId.from(db.accountExternalIds().all().toList());
|
Set<ExternalId> toAdd = new HashSet<>();
|
||||||
|
try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
|
||||||
|
ResultSet rs =
|
||||||
|
stmt.executeQuery(
|
||||||
|
"SELECT "
|
||||||
|
+ "account_id, "
|
||||||
|
+ "email_address, "
|
||||||
|
+ "password, "
|
||||||
|
+ "external_id "
|
||||||
|
+ "FROM account_external_ids")) {
|
||||||
|
while (rs.next()) {
|
||||||
|
Account.Id accountId = new Account.Id(rs.getInt(1));
|
||||||
|
String email = rs.getString(2);
|
||||||
|
String password = rs.getString(3);
|
||||||
|
String externalId = rs.getString(4);
|
||||||
|
|
||||||
|
toAdd.add(ExternalId.create(ExternalId.Key.parse(externalId), accountId, email, password));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try (Repository repo = repoManager.openRepository(allUsersName);
|
try (Repository repo = repoManager.openRepository(allUsersName);
|
||||||
RevWalk rw = new RevWalk(repo);
|
RevWalk rw = new RevWalk(repo);
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (C) 2017 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.schema;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
/** Drop ACCOUNT_EXTERNAL_IDS table. */
|
||||||
|
public class Schema_150 extends SchemaVersion {
|
||||||
|
@Inject
|
||||||
|
Schema_150(Provider<Schema_149> prior) {
|
||||||
|
super(prior);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,6 @@
|
||||||
package com.google.gerrit.testutil;
|
package com.google.gerrit.testutil;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.server.AccountAccess;
|
import com.google.gerrit.reviewdb.server.AccountAccess;
|
||||||
import com.google.gerrit.reviewdb.server.AccountExternalIdAccess;
|
|
||||||
import com.google.gerrit.reviewdb.server.AccountGroupAccess;
|
import com.google.gerrit.reviewdb.server.AccountGroupAccess;
|
||||||
import com.google.gerrit.reviewdb.server.AccountGroupByIdAccess;
|
import com.google.gerrit.reviewdb.server.AccountGroupByIdAccess;
|
||||||
import com.google.gerrit.reviewdb.server.AccountGroupByIdAudAccess;
|
import com.google.gerrit.reviewdb.server.AccountGroupByIdAudAccess;
|
||||||
|
@ -88,11 +87,6 @@ public class DisabledReviewDb implements ReviewDb {
|
||||||
throw new Disabled();
|
throw new Disabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AccountExternalIdAccess accountExternalIds() {
|
|
||||||
throw new Disabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccountGroupAccess accountGroups() {
|
public AccountGroupAccess accountGroups() {
|
||||||
throw new Disabled();
|
throw new Disabled();
|
||||||
|
|
|
@ -19,14 +19,12 @@ import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USE
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.gerrit.reviewdb.client.AccountSshKey;
|
import com.google.gerrit.reviewdb.client.AccountSshKey;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.account.VersionedAuthorizedKeys;
|
import com.google.gerrit.server.account.VersionedAuthorizedKeys;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalId;
|
import com.google.gerrit.server.account.externalids.ExternalId;
|
||||||
import com.google.gerrit.server.account.externalids.ExternalIds;
|
import com.google.gerrit.server.account.externalids.ExternalIds;
|
||||||
import com.google.gerrit.server.cache.CacheModule;
|
import com.google.gerrit.server.cache.CacheModule;
|
||||||
import com.google.gerrit.server.ssh.SshKeyCache;
|
import com.google.gerrit.server.ssh.SshKeyCache;
|
||||||
import com.google.gerrit.server.ssh.SshKeyCreator;
|
import com.google.gerrit.server.ssh.SshKeyCreator;
|
||||||
import com.google.gwtorm.server.SchemaFactory;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
@ -92,40 +90,33 @@ public class SshKeyCacheImpl implements SshKeyCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Loader extends CacheLoader<String, Iterable<SshKeyCacheEntry>> {
|
static class Loader extends CacheLoader<String, Iterable<SshKeyCacheEntry>> {
|
||||||
private final SchemaFactory<ReviewDb> schema;
|
|
||||||
private final ExternalIds externalIds;
|
private final ExternalIds externalIds;
|
||||||
private final VersionedAuthorizedKeys.Accessor authorizedKeys;
|
private final VersionedAuthorizedKeys.Accessor authorizedKeys;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Loader(
|
Loader(ExternalIds externalIds, VersionedAuthorizedKeys.Accessor authorizedKeys) {
|
||||||
SchemaFactory<ReviewDb> schema,
|
|
||||||
ExternalIds externalIds,
|
|
||||||
VersionedAuthorizedKeys.Accessor authorizedKeys) {
|
|
||||||
this.schema = schema;
|
|
||||||
this.externalIds = externalIds;
|
this.externalIds = externalIds;
|
||||||
this.authorizedKeys = authorizedKeys;
|
this.authorizedKeys = authorizedKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<SshKeyCacheEntry> load(String username) throws Exception {
|
public Iterable<SshKeyCacheEntry> load(String username) throws Exception {
|
||||||
try (ReviewDb db = schema.open()) {
|
ExternalId user = externalIds.get(ExternalId.Key.create(SCHEME_USERNAME, username));
|
||||||
ExternalId user = externalIds.get(db, ExternalId.Key.create(SCHEME_USERNAME, username));
|
if (user == null) {
|
||||||
if (user == null) {
|
return NO_SUCH_USER;
|
||||||
return NO_SUCH_USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<SshKeyCacheEntry> kl = new ArrayList<>(4);
|
|
||||||
for (AccountSshKey k : authorizedKeys.getKeys(user.accountId())) {
|
|
||||||
if (k.isValid()) {
|
|
||||||
add(kl, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kl.isEmpty()) {
|
|
||||||
return NO_KEYS;
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList(kl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<SshKeyCacheEntry> kl = new ArrayList<>(4);
|
||||||
|
for (AccountSshKey k : authorizedKeys.getKeys(user.accountId())) {
|
||||||
|
if (k.isValid()) {
|
||||||
|
add(kl, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kl.isEmpty()) {
|
||||||
|
return NO_KEYS;
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(kl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void add(List<SshKeyCacheEntry> kl, AccountSshKey k) {
|
private void add(List<SshKeyCacheEntry> kl, AccountSshKey k) {
|
||||||
|
|
Loading…
Reference in New Issue