// License: GPL. For details, see LICENSE file.
package org.openstreetmap.hot.sds;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Component;
import java.net.Authenticator.RequestorType;
import java.net.PasswordAuthentication;
import java.util.HashMap;
import java.util.Map;
import javax.swing.text.html.HTMLEditorKit;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.oauth.OAuthToken;
import org.openstreetmap.josm.gui.io.CredentialDialog;
import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
import org.openstreetmap.josm.gui.widgets.HtmlPanel;
import org.openstreetmap.josm.io.auth.AbstractCredentialsAgent;
import org.openstreetmap.josm.io.auth.CredentialsAgent;
import org.openstreetmap.josm.io.auth.CredentialsAgentException;
import org.openstreetmap.josm.io.auth.CredentialsAgentResponse;
/**
* Factored after JOSM's JosmPreferencesCredentialAgent.
*/
public class SdsCredentialAgent extends AbstractCredentialsAgent {
Map<RequestorType, PasswordAuthentication> sdsMemoryCredentialsCache = new HashMap<>();
/**
* @see CredentialsAgent#lookup(RequestorType)
*/
@Override
public PasswordAuthentication lookup(RequestorType requestorType, String host) throws CredentialsAgentException {
if (requestorType == null)
return null;
String user;
String password;
switch(requestorType) {
case SERVER:
user = Main.pref.get("sds-server.username", null);
password = Main.pref.get("sds-server.password", null);
if (user == null)
return null;
return new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
case PROXY:
user = Main.pref.get(ProxyPreferencesPanel.PROXY_USER, null);
password = Main.pref.get(ProxyPreferencesPanel.PROXY_PASS, null);
if (user == null)
return null;
return new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
}
return null;
}
/**
* @see CredentialsAgent#store(RequestorType, PasswordAuthentication)
*/
@Override
public void store(RequestorType requestorType, String host, PasswordAuthentication credentials) throws CredentialsAgentException {
if (requestorType == null)
return;
switch(requestorType) {
case SERVER:
Main.pref.put("sds-server.username", credentials.getUserName());
if (credentials.getPassword() == null) {
Main.pref.put("sds-server.password", null);
} else {
Main.pref.put("sds-server.password", String.valueOf(credentials.getPassword()));
}
break;
case PROXY:
Main.pref.put(ProxyPreferencesPanel.PROXY_USER, credentials.getUserName());
if (credentials.getPassword() == null) {
Main.pref.put(ProxyPreferencesPanel.PROXY_PASS, null);
} else {
Main.pref.put(ProxyPreferencesPanel.PROXY_PASS, String.valueOf(credentials.getPassword()));
}
break;
}
}
/**
* Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
* Access Token is currently managed by this CredentialManager.
*
* @return the current OAuth Access Token to access the OSM server.
* @throws CredentialsAgentException thrown if something goes wrong
*/
@Override
public OAuthToken lookupOAuthAccessToken() throws CredentialsAgentException {
String accessTokenKey = Main.pref.get("oauth.access-token.key", null);
String accessTokenSecret = Main.pref.get("oauth.access-token.secret", null);
if (accessTokenKey == null && accessTokenSecret == null)
return null;
return new OAuthToken(accessTokenKey, accessTokenSecret);
}
@Override
public Component getPreferencesDecorationPanel() {
HtmlPanel pnlMessage = new HtmlPanel();
HTMLEditorKit kit = (HTMLEditorKit) pnlMessage.getEditorPane().getEditorKit();
kit.getStyleSheet().addRule(
".warning-body {background-color:rgb(253,255,221);padding: 10pt; " +
"border-color:rgb(128,128,128);border-style: solid;border-width: 1px;}");
pnlMessage.setText(
tr(
"<html><body>"
+ "<p class=\"warning-body\">"
+ "<strong>Warning:</strong> The password is stored in plain text in the JOSM preferences file. "
+ "</p>"
+ "</body></html>"
)
);
return pnlMessage;
}
@Override
public String getSaveUsernameAndPasswordCheckboxText() {
return tr("Save user and password (unencrypted)");
}
@Override
public void storeOAuthAccessToken(OAuthToken accessToken)
throws CredentialsAgentException {
// no-op
}
@Override
public CredentialsAgentResponse getCredentials(RequestorType requestorType, String host, boolean noSuccessWithLastResponse)
throws CredentialsAgentException {
if (requestorType == null)
return null;
PasswordAuthentication credentials = lookup(requestorType, host);
String username = (credentials == null || credentials.getUserName() == null) ? "" : credentials.getUserName();
String password = (credentials == null || credentials.getPassword() == null) ? "" : String.valueOf(credentials.getPassword());
CredentialsAgentResponse response = new CredentialsAgentResponse();
/*
* Last request was successful and there was no credentials stored
* in file (or only the username is stored).
* -> Try to recall credentials that have been entered
* manually in this session.
*/
if (!noSuccessWithLastResponse && sdsMemoryCredentialsCache.containsKey(requestorType) &&
(credentials == null || credentials.getPassword() == null || credentials.getPassword().length == 0)) {
PasswordAuthentication pa = sdsMemoryCredentialsCache.get(requestorType);
response.setUsername(pa.getUserName());
response.setPassword(pa.getPassword());
response.setCanceled(false);
/*
* Prompt the user for credentials. This happens the first time each
* josm start if the user does not save the credentials to preference
* file (username=="") and each time after authentication failed
* (noSuccessWithLastResponse == true).
*/
} else if (noSuccessWithLastResponse || username.equals("") || password.equals("")) {
CredentialDialog dialog = null;
switch(requestorType) {
case SERVER:
dialog = SdsCredentialDialog.getSdsApiCredentialDialog(username, password, host, getSaveUsernameAndPasswordCheckboxText());
break;
case PROXY:
dialog = CredentialDialog.getHttpProxyCredentialDialog(username, password, host, getSaveUsernameAndPasswordCheckboxText());
break;
}
dialog.setVisible(true);
response.setCanceled(dialog.isCanceled());
if (dialog.isCanceled())
return response;
response.setUsername(dialog.getUsername());
response.setPassword(dialog.getPassword());
if (dialog.isSaveCredentials()) {
store(requestorType, host, new PasswordAuthentication(
response.getUsername(),
response.getPassword()
));
/*
* User decides not to save credentials to file. Keep it
* in memory so we don't have to ask over and over again.
*/
} else {
PasswordAuthentication pa = new PasswordAuthentication(dialog.getUsername(), dialog.getPassword());
sdsMemoryCredentialsCache.put(requestorType, pa);
}
/*
* We got it from file.
*/
} else {
response.setUsername(username);
response.setPassword(password.toCharArray());
response.setCanceled(false);
}
return response;
}
}