Skip to content

Commit

Permalink
CODENVY-687: Сache svn credentials instead of storing them in credent…
Browse files Browse the repository at this point in the history
…ials provider (#2672)
  • Loading branch information
Igor Vinokur committed Oct 5, 2016
1 parent 1123da1 commit 1103647
Show file tree
Hide file tree
Showing 65 changed files with 1,135 additions and 1,258 deletions.
Expand Up @@ -23,6 +23,7 @@ private ErrorCodes() {
public static final int NO_COMMITTER_NAME_OR_EMAIL_DEFINED = 15216;
public static final int UNABLE_GET_PRIVATE_SSH_KEY = 32068;
public static final int UNAUTHORIZED_GIT_OPERATION = 32080;
public static final int UNAUTHORIZED_SVN_OPERATION = 32090;
public static final int MERGE_CONFLICT = 32062;
public static final int FAILED_CHECKOUT = 32063;
public static final int FAILED_CHECKOUT_WITH_START_POINT = 32064;
Expand Down
@@ -0,0 +1,54 @@
/*******************************************************************************
* Copyright (c) 2012-2016 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.ide.api.subversion;

/**
* Credentials object for subversion operations.
*
* @author Igor Vinokur
*/
public class Credentials {
private String username;
private String password;

public Credentials(String username, String password) {
this.username = username;
this.password = password;
}

/**
* Returns user name for authentication.
*/
public String getUsername() {
return username;
}

/**
* Set user name for authentication.
*/
public void setUsername(String username) {
this.username = username;
}

/**
* Returns password for authentication.
*/
public String getPassword() {
return password;
}

/**
* Set password for authentication.
*/
public void setPassword(String password) {
this.password = password;
}
}
Expand Up @@ -8,18 +8,22 @@
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.svn.server.credentials;
//TODO This is used in wizard/ProjectImporter, find a solution to move it to plugin-svn.
package org.eclipse.che.ide.api.subversion;

public class CredentialsException extends Exception {
import org.eclipse.che.api.promises.client.Promise;

private static final long serialVersionUID = 1L;

public CredentialsException(final Throwable e) {
super(e);
}

public CredentialsException(final String message) {
super(message);
}
/**
* Dialog for retrieving credentials for SVN operations.
*
* @author Igor Vinokur
*/
public interface SubversionCredentialsDialog {

/**
* Returns credentials from dialog.
*
* @return {@link Credentials} that contains user name and password
*/
Promise<Credentials> askCredentials();
}
Expand Up @@ -29,6 +29,8 @@
import org.eclipse.che.ide.api.oauth.OAuth2Authenticator;
import org.eclipse.che.ide.api.oauth.OAuth2AuthenticatorRegistry;
import org.eclipse.che.ide.api.oauth.OAuth2AuthenticatorUrlProvider;
import org.eclipse.che.ide.api.subversion.Credentials;
import org.eclipse.che.ide.api.subversion.SubversionCredentialsDialog;
import org.eclipse.che.ide.api.project.MutableProjectConfig;
import org.eclipse.che.ide.api.project.wizard.ImportProjectNotificationSubscriberFactory;
import org.eclipse.che.ide.api.project.wizard.ProjectNotificationSubscriber;
Expand All @@ -45,6 +47,7 @@
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.che.api.core.ErrorCodes.UNABLE_GET_PRIVATE_SSH_KEY;
import static org.eclipse.che.api.core.ErrorCodes.UNAUTHORIZED_GIT_OPERATION;
import static org.eclipse.che.api.core.ErrorCodes.UNAUTHORIZED_SVN_OPERATION;
import static org.eclipse.che.api.git.shared.ProviderInfo.AUTHENTICATE_URL;
import static org.eclipse.che.api.git.shared.ProviderInfo.PROVIDER_NAME;
import static org.eclipse.che.api.promises.client.callback.AsyncPromiseHelper.createFromAsyncRequest;
Expand All @@ -60,6 +63,7 @@ public class ProjectImporter extends AbstractImporter {
private final CoreLocalizationConstant localizationConstant;
private final ProjectResolver projectResolver;
private final String restContext;
private final SubversionCredentialsDialog credentialsDialog;
private final OAuth2AuthenticatorRegistry oAuth2AuthenticatorRegistry;


Expand All @@ -69,11 +73,13 @@ public ProjectImporter(CoreLocalizationConstant localizationConstant,
AppContext appContext,
ProjectResolver projectResolver,
@RestContext String restContext,
SubversionCredentialsDialog credentialsDialog,
OAuth2AuthenticatorRegistry oAuth2AuthenticatorRegistry) {
super(appContext, subscriberFactory);
this.localizationConstant = localizationConstant;
this.projectResolver = projectResolver;
this.restContext = restContext;
this.credentialsDialog = credentialsDialog;
this.oAuth2AuthenticatorRegistry = oAuth2AuthenticatorRegistry;
}

Expand Down Expand Up @@ -136,6 +142,8 @@ public Promise<Project> apply(PromiseError exception) throws FunctionException {
switch (getErrorCode(exception.getCause())) {
case UNABLE_GET_PRIVATE_SSH_KEY:
throw new IllegalStateException(localizationConstant.importProjectMessageUnableGetSshKey());
case UNAUTHORIZED_SVN_OPERATION:
return recallImportWithCredentials(sourceStorage, path);
case UNAUTHORIZED_GIT_OPERATION:
final Map<String, String> attributes = ExceptionUtils.getAttributes(exception.getCause());
final String providerName = attributes.get(PROVIDER_NAME);
Expand All @@ -156,6 +164,32 @@ public Promise<Project> apply(PromiseError exception) throws FunctionException {
});
}

private Promise<Project> recallImportWithCredentials(final SourceStorage sourceStorage, final Path path) {
return createFromAsyncRequest(new RequestCall<Project>() {
@Override
public void makeCall(final AsyncCallback<Project> callback) {
credentialsDialog.askCredentials().then(new Operation<Credentials>() {
@Override
public void apply(Credentials credentials) throws OperationException {
sourceStorage.getParameters().put("username", credentials.getUsername());
sourceStorage.getParameters().put("password", credentials.getPassword());
doImport(path, sourceStorage).then(new Operation<Project>() {
@Override
public void apply(Project project) throws OperationException {
callback.onSuccess(project);
}
}).catchError(new Operation<PromiseError>() {
@Override
public void apply(PromiseError error) throws OperationException {
callback.onFailure(error.getCause());
}
});
}
});
}
});
}

private Promise<Project> authUserAndRecallImport(final String providerName,
final String authenticateUrl,
final Path path,
Expand Down
Expand Up @@ -95,6 +95,7 @@ public void setUp() {
appContext,
resolver,
null,
null,
null);
}

Expand Down
Expand Up @@ -11,6 +11,8 @@
package org.eclipse.che.plugin.svn.ide;

import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.api.subversion.Credentials;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.plugin.svn.shared.CLIOutputResponse;
import org.eclipse.che.plugin.svn.shared.CLIOutputResponseList;
Expand Down Expand Up @@ -84,34 +86,41 @@ Promise<CLIOutputResponse> add(Path project,
* source item path
* @param destination
* destination path
* @param credentials
* {@link Credentials} object that contains user name and password for authentication
*/
Promise<CLIOutputResponse> copy(Path project, Path source, Path destination, String comment);
Promise<CLIOutputResponse> copy(Path project,
Path source,
Path destination,
String comment,
@Nullable Credentials credentials);

/**
* Merge specified URL with target.
*
* @param project
* project path
* project path
* @param target
* target directory
* target directory
* @param sourceUrl
* source URL to merge
* source URL to merge
*/
Promise<CLIOutputResponse> merge(Path project, Path target, Path sourceUrl);

/**
* Retrieves the information about repository item.
*
* @param project
* relative path to the project in local workspace
* relative path to the project in local workspace
* @param target
* target to operate
* target to operate
* @param revision
* revision, use HEAD to specify latest revision
* @param children
* whether list children or not
* revision, use HEAD to specify latest revision
* @param credentials
* {@link Credentials} object that contains user name and password for authentication
*/
Promise<InfoResponse> info(Path project, Path target, String revision, boolean children);
Promise<InfoResponse> info(Path project, Path target, String revision, boolean children, @Nullable Credentials credentials);

Promise<InfoResponse> info(Path project, String target, String revision, boolean children);

/**
Expand Down Expand Up @@ -161,12 +170,20 @@ Promise<CLIOutputResponse> status(Path project,
* whether or not to ignore externals (--ignore-externals)
* @param accept
* the accept argument (--accept)
* @param credentials
* {@link Credentials} object that contains user name and password for authentication
*/
Promise<CLIOutputWithRevisionResponse> update(Path project, Path[] paths, String revision, String depth, boolean ignoreExternals, String accept);
Promise<CLIOutputWithRevisionResponse> update(Path project,
Path[] paths,
String revision,
String depth,
boolean ignoreExternals,
String accept,
@Nullable Credentials credentials);

Promise<CLIOutputResponse> showLog(Path project, Path[] paths, String revision);

Promise<CLIOutputResponse> showDiff(Path project, Path[] paths, String revision);
Promise<CLIOutputResponse> showDiff(Path project, Path[] paths, String revision, @Nullable Credentials credentials);

/**
* Locks the given paths.
Expand All @@ -178,8 +195,10 @@ Promise<CLIOutputResponse> status(Path project,
* @param force
* if false, will warn if another user already has a lock on a target, leave this target unchanged, and continue.<br>
* if true, will steal the lock from the previous owner instead
* @param credentials
* {@link Credentials} object that contains user name and password for authentication
*/
Promise<CLIOutputResponse> lock(Path project, Path[] paths, boolean force);
Promise<CLIOutputResponse> lock(Path project, Path[] paths, boolean force, @Nullable Credentials credentials);

/**
* Unocks the given paths.
Expand All @@ -191,8 +210,10 @@ Promise<CLIOutputResponse> status(Path project,
* @param force
* if false, will warn if another user already has a lock on a target, leave this target unchanged, and continue.<br>
* if true, will unlock anyway
* @param credentials
* {@link Credentials} object that contains user name and password for authentication
*/
Promise<CLIOutputResponse> unlock(Path project, Path[] paths, boolean force);
Promise<CLIOutputResponse> unlock(Path project, Path[] paths, boolean force, @Nullable Credentials credentials);

/**
* Commits the changes in the repository.
Expand Down Expand Up @@ -224,19 +245,21 @@ Promise<CLIOutputResponse> status(Path project,

Promise<CLIOutputResponseList> resolve(Path project, Map<String, String> resolutions, String depth);

Promise<Void> saveCredentials(String repositoryUrl, String username, String password);

/**
* Move provided path.
*
* @param project
* the project path
* @param source
* source item path
* @param destination
* destination path
* @param credentials
* {@link Credentials} object that contains user name and password for authentication
*/
Promise<CLIOutputResponse> move(Path project, Path source, Path destination, String comment);
Promise<CLIOutputResponse> move(Path project,
Path source,
Path destination,
String comment,
@Nullable Credentials credentials);

/**
* Set specified property to a path or a target.
Expand All @@ -259,17 +282,22 @@ Promise<CLIOutputResponse> status(Path project,
/**
* Get specified property for a path or a target.
*
* @param project the project path
* @param propertyName the property name
* @param path path to which property get
* @param project
* the project path
* @param propertyName
* the property name
* @param path
* path to which property get
*/
Promise<CLIOutputResponse> propertyGet(Path project, String propertyName, Path path);

/**
* Get properties set for a path or a target.
*
* @param project the project path
* @param path path to which property get
* @param project
* the project path
* @param path
* path to which property get
*/
Promise<CLIOutputResponse> propertyList(Path project, Path path);

Expand Down

0 comments on commit 1103647

Please sign in to comment.