Adapt WebUI to use REST endpoint for deleting SSH keys

The old RPC for deleting SSH keys is removed.

Change-Id: Ib7021122b2de68c3a2f0ebcc70c3a1459d4c8bf2
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2013-06-03 15:41:58 +02:00
committed by Shawn Pearce
parent 5a02ffda99
commit c950bcca7e
5 changed files with 76 additions and 69 deletions

View File

@@ -18,7 +18,6 @@ import com.google.gerrit.common.audit.Audit;
import com.google.gerrit.common.auth.SignInRequired;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.reviewdb.client.ContactInformation;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.RemoteJsonService;
@@ -31,11 +30,6 @@ import java.util.Set;
@RpcImpl(version = Version.V2_0)
public interface AccountSecurity extends RemoteJsonService {
@Audit
@SignInRequired
void deleteSshKeys(Set<AccountSshKey.Id> ids,
AsyncCallback<VoidResult> callback);
@Audit
@SignInRequired
void changeUserName(String newName, AsyncCallback<VoidResult> callback);

View File

@@ -15,12 +15,15 @@
package com.google.gerrit.client.account;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.rpc.AsyncCallback;
import java.util.Set;
/**
* A collection of static methods which work on the Gerrit REST API for specific
* accounts.
@@ -47,6 +50,23 @@ public class AccountApi {
.post(sshPublicKey, cb);
}
/**
* Delete SSH keys. For each key to be deleted a separate DELETE request is
* fired to the server. The {@code onSuccess} method of the provided callback
* is invoked once after all requests succeeded. If any request fails the
* callbacks' {@code onFailure} method is invoked. In a failure case it can be
* that still some of the keys were successfully deleted.
*/
public static void deleteSshKeys(String account,
Set<Integer> sequenceNumbers, AsyncCallback<VoidResult> cb) {
CallbackGroup group = new CallbackGroup();
for (int seq : sequenceNumbers) {
new RestApi("/accounts/").id(account).view("sshkeys").id(seq)
.delete(group.add(cb));
cb = CallbackGroup.emptyCallback();
}
}
/** Generate a new HTTP password */
public static void generateHttpPassword(String account,
AsyncCallback<NativeString> cb) {

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.client.account;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.ComplexDisclosurePanel;
@@ -23,7 +24,6 @@ import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.data.SshHostKey;
import com.google.gerrit.common.errors.InvalidSshKeyException;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -42,7 +42,6 @@ import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.globalkey.client.NpTextArea;
import com.google.gwtjsonrpc.client.RemoteJsonException;
import com.google.gwtjsonrpc.common.VoidResult;
import java.util.Collections;
import java.util.HashSet;
@@ -197,25 +196,27 @@ class SshPanel extends Composite {
@Override
protected void onLoad() {
super.onLoad();
AccountApi.getSshKeys("self", new GerritCallback<JsArray<SshKeyInfo>>() {
@Override
public void onSuccess(JsArray<SshKeyInfo> result) {
keys.display(Natives.asList(result));
if (result.length() == 0 && keys.isVisible()) {
showAddKeyBlock(true);
refreshSshKeys();
Gerrit.SYSTEM_SVC.daemonHostKeys(new GerritCallback<List<SshHostKey>>() {
public void onSuccess(final List<SshHostKey> result) {
serverKeys.clear();
for (final SshHostKey keyInfo : result) {
serverKeys.add(new SshHostKeyPanel(keyInfo));
}
if (++loadCount == 2) {
display();
}
}
});
}
Gerrit.SYSTEM_SVC.daemonHostKeys(new GerritCallback<List<SshHostKey>>() {
public void onSuccess(final List<SshHostKey> result) {
serverKeys.clear();
for (final SshHostKey keyInfo : result) {
serverKeys.add(new SshHostKeyPanel(keyInfo));
private void refreshSshKeys() {
AccountApi.getSshKeys("self", new GerritCallback<JsArray<SshKeyInfo>>() {
@Override
public void onSuccess(JsArray<SshKeyInfo> result) {
keys.display(Natives.asList(result));
if (result.length() == 0 && keys.isVisible()) {
showAddKeyBlock(true);
}
if (++loadCount == 2) {
display();
@@ -258,35 +259,41 @@ class SshPanel extends Composite {
}
void deleteChecked() {
final HashSet<AccountSshKey.Id> ids = new HashSet<AccountSshKey.Id>();
final HashSet<Integer> sequenceNumbers = new HashSet<Integer>();
for (int row = 1; row < table.getRowCount(); row++) {
final SshKeyInfo k = getRowItem(row);
if (k != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
ids.add(new AccountSshKey.Id(Gerrit.getUserAccount().getId(), k.seq()));
sequenceNumbers.add(k.seq());
}
}
if (ids.isEmpty()) {
if (sequenceNumbers.isEmpty()) {
updateDeleteButton();
} else {
Util.ACCOUNT_SEC.deleteSshKeys(ids, new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) {
for (int row = 1; row < table.getRowCount();) {
final SshKeyInfo k = getRowItem(row);
if (k != null
&& ids.contains(new AccountSshKey.Id(Gerrit.getUserAccount()
.getId(), k.seq()))) {
table.removeRow(row);
} else {
row++;
AccountApi.deleteSshKeys("self", sequenceNumbers,
new GerritCallback<VoidResult>() {
public void onSuccess(VoidResult result) {
for (int row = 1; row < table.getRowCount();) {
final SshKeyInfo k = getRowItem(row);
if (k != null && sequenceNumbers.contains(k.seq())) {
table.removeRow(row);
} else {
row++;
}
}
if (table.getRowCount() == 1) {
display(Collections.<SshKeyInfo> emptyList());
} else {
updateDeleteButton();
}
}
}
if (table.getRowCount() == 1) {
display(Collections.<SshKeyInfo> emptyList());
} else {
updateDeleteButton();
}
}
});
@Override
public void onFailure(Throwable caught) {
refreshSshKeys();
updateDeleteButton();
super.onFailure(caught);
}
});
}
}

View File

@@ -43,6 +43,18 @@ public class CallbackGroup {
private final Map<Object, Object> results;
private boolean failed;
public static <T> AsyncCallback<T> emptyCallback() {
return new AsyncCallback<T>() {
@Override
public void onSuccess(T result) {
}
@Override
public void onFailure(Throwable err) {
}
};
}
public CallbackGroup() {
callbacks = new ArrayList<Object>();
results = new HashMap<Object, Object>();

View File

@@ -28,7 +28,6 @@ import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.reviewdb.client.ContactInformation;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
@@ -43,7 +42,6 @@ import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.contact.ContactStore;
import com.google.gerrit.server.mail.EmailTokenVerifier;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.ssh.SshKeyCache;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtorm.server.OrmException;
@@ -61,7 +59,6 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
private final ProjectCache projectCache;
private final Provider<IdentifiedUser> user;
private final EmailTokenVerifier emailTokenVerifier;
private final SshKeyCache sshKeyCache;
private final AccountByEmailCache byEmailCache;
private final AccountCache accountCache;
private final AccountManager accountManager;
@@ -79,8 +76,8 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
final Provider<CurrentUser> currentUser, final ContactStore cs,
final Realm r, final Provider<IdentifiedUser> u,
final EmailTokenVerifier etv, final ProjectCache pc,
final SshKeyCache skc, final AccountByEmailCache abec,
final AccountCache uac, final AccountManager am,
final AccountByEmailCache abec, final AccountCache uac,
final AccountManager am,
final ChangeUserName.CurrentUser changeUserNameFactory,
final DeleteExternalIds.Factory deleteExternalIdsFactory,
final ExternalIdDetailFactory.Factory externalIdDetailFactory,
@@ -91,7 +88,6 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
user = u;
emailTokenVerifier = etv;
projectCache = pc;
sshKeyCache = skc;
byEmailCache = abec;
accountCache = uac;
accountManager = am;
@@ -105,28 +101,6 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
this.groupCache = groupCache;
}
public void deleteSshKeys(final Set<AccountSshKey.Id> ids,
final AsyncCallback<VoidResult> callback) {
run(callback, new Action<VoidResult>() {
public VoidResult run(final ReviewDb db) throws OrmException, Failure {
final Account.Id me = user.get().getAccountId();
for (final AccountSshKey.Id keyId : ids) {
if (!me.equals(keyId.getParentKey()))
throw new Failure(new NoSuchEntityException());
}
db.accountSshKeys().deleteKeys(ids);
uncacheSshKeys();
return VoidResult.INSTANCE;
}
});
}
private void uncacheSshKeys() {
sshKeyCache.evict(user.get().getUserName());
}
@Override
public void changeUserName(final String newName,
final AsyncCallback<VoidResult> callback) {