blob: 01f9083da80857da1481f84b9ca739c33afcba17 [file] [log] [blame]
// Copyright 2008-2010 Victor Iacoban
//
// 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 org.zmlx.hg4idea.execution;
import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.config.PasswordSafeSettings;
import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.vcsUtil.AuthDialog;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgGlobalSettings;
import org.zmlx.hg4idea.HgVcs;
import org.zmlx.hg4idea.HgVcsMessages;
/**
* Base class for any command interacting with a remote repository and which needs authentication.
*/
class HgCommandAuthenticator {
private static final Logger LOG = Logger.getInstance(HgCommandAuthenticator.class.getName());
private GetPasswordRunnable myGetPassword;
private final Project myProject;
private boolean myForceAuthorization;
//todo replace silent mode and/or force authorization
private boolean mySilentMode;
public HgCommandAuthenticator(Project project, boolean forceAuthorization, boolean silent) {
myProject = project;
myForceAuthorization = forceAuthorization;
mySilentMode = silent;
}
public void saveCredentials() {
if (myGetPassword == null) return;
// if checkbox is selected, save on disk. Otherwise in memory. Don't read password safe settings.
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
final String url = VirtualFileManager.extractPath(myGetPassword.getURL());
final String key = keyForUrlAndLogin(url, myGetPassword.getUserName());
try {
if (myGetPassword.isRememberPassword()) {
PasswordSafe.getInstance().storePassword(myProject, HgCommandAuthenticator.class, key, myGetPassword.getPassword());
}
else if (passwordSafe.getSettings().getProviderType() != PasswordSafeSettings.ProviderType.DO_NOT_STORE) {
passwordSafe.getMemoryProvider().storePassword(myProject, HgCommandAuthenticator.class, key, myGetPassword.getPassword());
}
final HgVcs vcs = HgVcs.getInstance(myProject);
if (vcs != null) {
vcs.getGlobalSettings().addRememberedUrl(url, myGetPassword.getUserName());
}
}
catch (PasswordSafeException e) {
LOG.info("Couldn't store the password for key [" + key + "]", e);
}
}
public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path, @Nullable ModalityState state) {
GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization, mySilentMode);
ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state);
myGetPassword = runnable;
return runnable.isOk();
}
public String getUserName() {
return myGetPassword.getUserName();
}
public String getPassword() {
return myGetPassword.getPassword();
}
private static class GetPasswordRunnable implements Runnable {
private static final Logger LOG = Logger.getInstance(GetPasswordRunnable.class.getName());
private String myUserName;
private String myPassword;
private Project myProject;
private final String myProposedLogin;
private boolean ok = false;
@Nullable private String myURL;
private boolean myRememberPassword;
private boolean myForceAuthorization;
private final boolean mySilent;
public GetPasswordRunnable(Project project,
String proposedLogin,
String uri,
String path,
boolean forceAuthorization, boolean silent) {
this.myProject = project;
this.myProposedLogin = proposedLogin;
this.myURL = uri + path;
this.myForceAuthorization = forceAuthorization;
mySilent = silent;
}
public void run() {
// find if we've already been here
final HgVcs vcs = HgVcs.getInstance(myProject);
if (vcs == null) {
return;
}
@NotNull final HgGlobalSettings hgGlobalSettings = vcs.getGlobalSettings();
@Nullable String rememberedLoginsForUrl = null;
if (!StringUtil.isEmptyOrSpaces(myURL)) {
rememberedLoginsForUrl = hgGlobalSettings.getRememberedUserName(VirtualFileManager.extractPath(myURL));
}
String login = myProposedLogin;
if (StringUtil.isEmptyOrSpaces(login)) {
// find the last used login
login = rememberedLoginsForUrl;
}
String password = null;
if (!StringUtil.isEmptyOrSpaces(login) && myURL != null) {
// if we've logged in with this login, search for password
final String key = keyForUrlAndLogin(myURL, login);
try {
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
if (mySilent) {
password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
}
else {
password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key);
}
}
catch (PasswordSafeException e) {
LOG.info("Couldn't get password for key [" + key + "]", e);
}
}
// don't show dialog if we don't have to (both fields are known) except force authorization required
if (!myForceAuthorization && !StringUtil.isEmptyOrSpaces(
password) && !StringUtil.isEmptyOrSpaces(login)) {
myUserName = login;
myPassword = password;
ok = true;
return;
}
if (mySilent) {
ok = false;
return;
}
final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"),
HgVcsMessages.message("hg4idea.dialog.login.description", myURL),
login, password, true);
dialog.show();
if (dialog.isOK()) {
myUserName = dialog.getUsername();
myPassword = dialog.getPassword();
myRememberPassword = dialog.isRememberPassword();
ok = true;
}
}
public String getUserName() {
return myUserName;
}
public String getPassword() {
return myPassword;
}
public boolean isOk() {
return ok;
}
@Nullable
public String getURL() {
return myURL;
}
public boolean isRememberPassword() {
return myRememberPassword;
}
}
private static String keyForUrlAndLogin(String stringUrl, String login) {
return login + ":" + stringUrl;
}
}