Add REST endpoint to get account external IDs

Add a new endpoint /accounts/{id}/external.ids which will return a
list of the external IDs for the given account. It is only allowed
to get this list for a user's own account.

To determine whether or not the user can delete an external ID, we
need to know if that ID was used to log into the current session.

The WebSession is not available outside of gerrit-httpd, so pass the
external ID through a property on the current user.

Change-Id: Iab7ef2ffa06c3a8d9f22472308051b4b73668f82
This commit is contained in:
Changcheng Xiao
2017-01-10 13:03:53 +01:00
parent 6c5fa05cdd
commit 0748e7441d
8 changed files with 222 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
// 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.account;
import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.common.AccountExternalIdInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.AuthConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@Singleton
public class GetExternalIds implements RestReadView<AccountResource> {
private final ExternalIdCache externalIdCache;
private final Provider<CurrentUser> self;
private final AuthConfig authConfig;
@Inject
GetExternalIds(ExternalIdCache externalIdCache,
Provider<CurrentUser> self,
AuthConfig authConfig) {
this.externalIdCache = externalIdCache;
this.self = self;
this.authConfig = authConfig;
}
@Override
public List<AccountExternalIdInfo> apply(AccountResource resource)
throws RestApiException {
if (self.get() != resource.getUser()) {
throw new AuthException("not allowed to get external IDs");
}
Collection<AccountExternalId> ids = externalIdCache.byAccount(
resource.getUser().getAccountId());
if (ids.isEmpty()) {
return ImmutableList.of();
}
List<AccountExternalIdInfo> result =
Lists.newArrayListWithCapacity(ids.size());
for (AccountExternalId id : ids) {
AccountExternalIdInfo info = new AccountExternalIdInfo();
info.identity = id.getExternalId();
info.emailAddress = id.getEmailAddress();
info.trusted = authConfig.isIdentityTrustable(
Collections.singleton(id));
// The identity can be deleted only if its not the one used to
// establish this web session, and if only if an identity was
// actually used to establish this web session.
if (id.isScheme(SCHEME_USERNAME)) {
info.canDelete = false;
} else {
CurrentUser.PropertyKey<AccountExternalId.Key> k =
CurrentUser.PropertyKey.create();
AccountExternalId.Key last = resource.getUser().get(k);
info.canDelete = (last != null) && (!last.get().equals(info.identity));
}
result.add(info);
}
return result;
}
}

View File

@@ -95,6 +95,8 @@ public class Module extends RestApiModule {
get(STAR_KIND).to(Stars.Get.class);
post(STAR_KIND).to(Stars.Post.class);
get(ACCOUNT_KIND, "external.ids").to(GetExternalIds.class);
factory(CreateAccount.Factory.class);
factory(CreateEmail.Factory.class);
}

View File

@@ -26,6 +26,7 @@ import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.client.EditPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.ProjectWatchInfo;
import com.google.gerrit.extensions.common.AccountExternalIdInfo;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.AgreementInfo;
import com.google.gerrit.extensions.common.AgreementInput;
@@ -49,6 +50,7 @@ import com.google.gerrit.server.account.GetAgreements;
import com.google.gerrit.server.account.GetAvatar;
import com.google.gerrit.server.account.GetDiffPreferences;
import com.google.gerrit.server.account.GetEditPreferences;
import com.google.gerrit.server.account.GetExternalIds;
import com.google.gerrit.server.account.GetPreferences;
import com.google.gerrit.server.account.GetSshKeys;
import com.google.gerrit.server.account.GetWatchedProjects;
@@ -110,6 +112,7 @@ public class AccountApiImpl implements AccountApi {
private final PutActive putActive;
private final DeleteActive deleteActive;
private final Index index;
private final GetExternalIds getExternalIds;
@Inject
AccountApiImpl(AccountLoader.Factory ailf,
@@ -141,6 +144,7 @@ public class AccountApiImpl implements AccountApi {
PutActive putActive,
DeleteActive deleteActive,
Index index,
GetExternalIds getExternalIds,
@Assisted AccountResource account) {
this.account = account;
this.accountLoaderFactory = ailf;
@@ -172,6 +176,7 @@ public class AccountApiImpl implements AccountApi {
this.putActive = putActive;
this.deleteActive = deleteActive;
this.index = index;
this.getExternalIds = getExternalIds;
}
@Override
@@ -447,4 +452,9 @@ public class AccountApiImpl implements AccountApi {
throw new RestApiException("Cannot index account", e);
}
}
@Override
public List<AccountExternalIdInfo> getExternalIds() throws RestApiException {
return getExternalIds.apply(account);
}
}