/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.plugin.ssh.key.client.manage; import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.inject.Inject; import com.google.inject.Singleton; import org.eclipse.che.api.promises.client.Operation; import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.api.promises.client.PromiseError; import org.eclipse.che.api.ssh.shared.dto.SshPairDto; import org.eclipse.che.ide.api.app.AppContext; import org.eclipse.che.ide.api.app.CurrentUser; import org.eclipse.che.ide.api.dialogs.CancelCallback; import org.eclipse.che.ide.api.dialogs.ConfirmCallback; import org.eclipse.che.ide.api.dialogs.DialogFactory; import org.eclipse.che.ide.api.dialogs.InputCallback; import org.eclipse.che.ide.api.dialogs.InputValidator; import org.eclipse.che.ide.api.notification.NotificationManager; import org.eclipse.che.ide.api.preferences.AbstractPreferencePagePresenter; import org.eclipse.che.ide.api.ssh.SshServiceClient; import org.eclipse.che.plugin.ssh.key.client.SshKeyLocalizationConstant; import org.eclipse.che.plugin.ssh.key.client.SshKeyUploader; import org.eclipse.che.plugin.ssh.key.client.SshKeyUploaderRegistry; import org.eclipse.che.plugin.ssh.key.client.upload.UploadSshKeyPresenter; import javax.validation.constraints.NotNull; import java.util.List; import static org.eclipse.che.ide.api.notification.StatusNotification.DisplayMode.FLOAT_MODE; import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL; /** * The presenter for managing ssh keys. * * @author Evgen Vidolob * @author Sergii Leschenko */ @Singleton public class SshKeyManagerPresenter extends AbstractPreferencePagePresenter implements SshKeyManagerView.ActionDelegate { public static final String GITHUB_HOST = "github.com"; public static final String VCS_SSH_SERVICE = "vcs"; private final AppContext appContext; private final DialogFactory dialogFactory; private final SshKeyManagerView view; private final SshServiceClient service; private final SshKeyUploaderRegistry registry; private final ShowSshKeyView showSshKeyView; private final SshKeyLocalizationConstant constant; private final UploadSshKeyPresenter uploadSshKeyPresenter; private final NotificationManager notificationManager; final HostNameValidator hostNameValidator; @Inject public SshKeyManagerPresenter(SshKeyManagerView view, SshServiceClient service, AppContext appContext, SshKeyLocalizationConstant constant, UploadSshKeyPresenter uploadSshKeyPresenter, NotificationManager notificationManager, DialogFactory dialogFactory, SshKeyUploaderRegistry registry, ShowSshKeyView showSshKeyView) { super(constant.sshManagerTitle(), constant.sshManagerCategory()); this.view = view; this.appContext = appContext; this.dialogFactory = dialogFactory; this.registry = registry; this.showSshKeyView = showSshKeyView; this.view.setDelegate(this); this.service = service; this.constant = constant; this.uploadSshKeyPresenter = uploadSshKeyPresenter; this.notificationManager = notificationManager; this.hostNameValidator = new HostNameValidator(); } /** {@inheritDoc} */ @Override public void onViewClicked(@NotNull final SshPairDto pair) { showSshKeyView.show(pair.getName(), pair.getPublicKey()); } /** {@inheritDoc} */ @Override public void onDeleteClicked(@NotNull final SshPairDto pair) { dialogFactory.createConfirmDialog(constant.deleteSshKeyTitle(), constant.deleteSshKeyQuestion(pair.getName()).asString(), new ConfirmCallback() { @Override public void accepted() { deleteKey(pair); } }, getCancelCallback()).show(); } private CancelCallback getCancelCallback() { return new CancelCallback() { @Override public void cancelled() { //for now do nothing but it need for tests } }; } private void deleteKey(final SshPairDto key) { service.deletePair(key.getService(), key.getName()) .then(new Operation<Void>() { @Override public void apply(Void arg) throws OperationException { refreshKeys(); } }) .catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError arg) throws OperationException { notificationManager.notify(arg.getMessage(), FAIL, FLOAT_MODE); } }); } /** {@inheritDoc} */ @Override public void onGenerateClicked() { dialogFactory.createInputDialog(constant.generateSshKeyTitle(), constant.generateSshKeyHostname(), new InputCallback() { @Override public void accepted(String host) { generateKey(host); } }, getCancelCallback()) .withValidator(hostNameValidator) .show(); } private void generateKey(String host) { service.generatePair(VCS_SSH_SERVICE, host) .then(new Operation<SshPairDto>() { @Override public void apply(SshPairDto arg) throws OperationException { refreshKeys(); } }) .catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError arg) throws OperationException { notificationManager.notify(constant.failedToGenerateSshKey(), arg.getMessage(), FAIL, FLOAT_MODE); } }); } /** {@inheritDoc} */ @Override public void onUploadClicked() { uploadSshKeyPresenter.showDialog(new AsyncCallback<Void>() { @Override public void onSuccess(Void result) { refreshKeys(); } @Override public void onFailure(Throwable caught) { } }); } /** {@inheritDoc} */ @Override public void onGenerateGithubKeyClicked() { CurrentUser user = appContext.getCurrentUser(); final SshKeyUploader githubUploader = registry.getUploaders().get(GITHUB_HOST); if (user != null && githubUploader != null) { githubUploader.uploadKey(user.getProfile().getUserId(), new AsyncCallback<Void>() { @Override public void onSuccess(Void result) { refreshKeys(); } @Override public void onFailure(Throwable exception) { removeFailedKey(GITHUB_HOST); } }); } else { notificationManager.notify(constant.failedToGenerateSshKey(), constant.sshKeysProviderNotFound(GITHUB_HOST), FAIL, FLOAT_MODE); } } /** Need to remove failed uploaded keys from local storage if they can't be uploaded */ private void removeFailedKey(final String host) { service.getPairs(VCS_SSH_SERVICE) .then(new Operation<List<SshPairDto>>() { @Override public void apply(List<SshPairDto> result) throws OperationException { for (SshPairDto key : result) { if (key.getName().equals(host)) { removeFailedKey(key); return; } } refreshKeys(); } }) .catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError arg) throws OperationException { refreshKeys(); notificationManager.notify(constant.failedToLoadSshKeys(), FAIL, FLOAT_MODE); } }); } /** * Remove failed key. * * @param key * failed key */ private void removeFailedKey(@NotNull final SshPairDto key) { service.deletePair(key.getService(), key.getName()) .then(new Operation<Void>() { @Override public void apply(Void arg) throws OperationException { refreshKeys(); } }) .catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError arg) throws OperationException { notificationManager.notify(constant.deleteSshKeyFailed(), FAIL, FLOAT_MODE); refreshKeys(); } }); } /** {@inheritDoc} */ @Override public boolean isDirty() { return false; } /** {@inheritDoc} */ @Override public void go(AcceptsOneWidget container) { refreshKeys(); container.setWidget(view); } /** Refresh ssh keys. */ private void refreshKeys() { service.getPairs(VCS_SSH_SERVICE) .then(new Operation<List<SshPairDto>>() { @Override public void apply(List<SshPairDto> result) throws OperationException { view.setPairs(result); } }) .catchError(new Operation<PromiseError>() { @Override public void apply(PromiseError arg) throws OperationException { notificationManager.notify(constant.failedToLoadSshKeys(), FAIL, FLOAT_MODE); } }); } @Override public void storeChanges() { } @Override public void revertChanges() { } private class HostNameValidator implements InputValidator { private final RegExp hostNamePattern; HostNameValidator() { hostNamePattern = RegExp.compile("^([a-zA-Z0-9](\\.|\\-)?)*[a-zA-Z0-9]+$"); } @Override public Violation validate(String value) { if (!hostNamePattern.test(value)) { return new Violation() { @Override public String getMessage() { return constant.invalidHostName(); } @Override public String getCorrectedValue() { return null; } }; } return null; } } }