001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.server;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.BorderLayout;
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.awt.Insets;
010import java.awt.event.ItemEvent;
011import java.awt.event.ItemListener;
012import java.beans.PropertyChangeEvent;
013import java.beans.PropertyChangeListener;
014
015import javax.swing.ButtonGroup;
016import javax.swing.JPanel;
017import javax.swing.JRadioButton;
018
019import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
020import org.openstreetmap.josm.gui.help.HelpUtil;
021import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
022import org.openstreetmap.josm.io.OsmApi;
023import org.openstreetmap.josm.io.auth.CredentialsManager;
024import org.openstreetmap.josm.spi.preferences.Config;
025import org.openstreetmap.josm.tools.Logging;
026
027/**
028 * This is the preference panel for the authentication method and the authentication parameters.
029 * @since 2745
030 */
031public class AuthenticationPreferencesPanel extends VerticallyScrollablePanel implements PropertyChangeListener {
032
033    /** indicates whether we use basic authentication */
034    private final JRadioButton rbBasicAuthentication = new JRadioButton();
035    /** indicates whether we use OAuth as authentication scheme */
036    private final JRadioButton rbOAuth = new JRadioButton();
037    /** the panel which contains the authentication parameters for the respective authentication scheme */
038    private final JPanel pnlAuthenticationParameters = new JPanel(new BorderLayout());
039    /** the panel for the basic authentication parameters */
040    private BasicAuthenticationPreferencesPanel pnlBasicAuthPreferences;
041    /** the panel for the OAuth authentication parameters */
042    private OAuthAuthenticationPreferencesPanel pnlOAuthPreferences;
043
044    /**
045     * Constructs a new {@code AuthenticationPreferencesPanel}.
046     */
047    public AuthenticationPreferencesPanel() {
048        build();
049        initFromPreferences();
050        HelpUtil.setHelpContext(this, HelpUtil.ht("/Preferences/Connection#AuthenticationSettings"));
051    }
052
053    /**
054     * builds the UI
055     */
056    protected final void build() {
057        setLayout(new GridBagLayout());
058        GridBagConstraints gc = new GridBagConstraints();
059
060        AuthenticationMethodChangeListener authChangeListener = new AuthenticationMethodChangeListener();
061
062        // -- radio button for basic authentication
063        gc.anchor = GridBagConstraints.NORTHWEST;
064        gc.fill = GridBagConstraints.HORIZONTAL;
065        gc.gridx = 1;
066        gc.weightx = 1.0;
067        gc.insets = new Insets(0, 0, 0, 3);
068        add(rbBasicAuthentication, gc);
069        rbBasicAuthentication.setText(tr("Use Basic Authentication"));
070        rbBasicAuthentication.setToolTipText(tr("Select to use HTTP basic authentication with your OSM username and password"));
071        rbBasicAuthentication.addItemListener(authChangeListener);
072
073        //-- radio button for OAuth
074        gc.gridx = 0;
075        gc.weightx = 0.0;
076        add(rbOAuth, gc);
077        rbOAuth.setText(tr("Use OAuth"));
078        rbOAuth.setToolTipText(tr("Select to use OAuth as authentication mechanism"));
079        rbOAuth.addItemListener(authChangeListener);
080
081        //-- radio button for OAuth
082        ButtonGroup bg = new ButtonGroup();
083        bg.add(rbBasicAuthentication);
084        bg.add(rbOAuth);
085
086        //-- add the panel which will hold the authentication parameters
087        gc.gridx = 0;
088        gc.gridy = 1;
089        gc.gridwidth = 2;
090        gc.fill = GridBagConstraints.BOTH;
091        gc.weightx = 1.0;
092        gc.weighty = 1.0;
093        add(pnlAuthenticationParameters, gc);
094
095        //-- the two panels for authentication parameters
096        pnlBasicAuthPreferences = new BasicAuthenticationPreferencesPanel();
097        pnlOAuthPreferences = new OAuthAuthenticationPreferencesPanel();
098
099        rbBasicAuthentication.setSelected(true);
100        pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
101    }
102
103    /**
104     * Initializes the panel from preferences
105     */
106    public final void initFromPreferences() {
107        final String authMethod = OsmApi.getAuthMethod();
108        if ("basic".equals(authMethod)) {
109            rbBasicAuthentication.setSelected(true);
110        } else if ("oauth".equals(authMethod)) {
111            rbOAuth.setSelected(true);
112        } else {
113            Logging.warn(tr("Unsupported value in preference ''{0}'', got ''{1}''. Using authentication method ''Basic Authentication''.",
114                    "osm-server.auth-method", authMethod));
115            rbBasicAuthentication.setSelected(true);
116        }
117        pnlBasicAuthPreferences.initFromPreferences();
118        pnlOAuthPreferences.initFromPreferences();
119    }
120
121    /**
122     * Saves the current values to the preferences
123     */
124    public final void saveToPreferences() {
125        // save the authentication method
126        String authMethod;
127        if (rbBasicAuthentication.isSelected()) {
128            authMethod = "basic";
129        } else {
130            authMethod = "oauth";
131        }
132        Config.getPref().put("osm-server.auth-method", authMethod);
133        if ("basic".equals(authMethod)) {
134            // save username and password and clear the OAuth token
135            pnlBasicAuthPreferences.saveToPreferences();
136            OAuthAccessTokenHolder.getInstance().clear();
137            OAuthAccessTokenHolder.getInstance().save(CredentialsManager.getInstance());
138        } else if ("oauth".equals(authMethod)) {
139            // clear the password in the preferences
140            pnlBasicAuthPreferences.clearPassword();
141            pnlBasicAuthPreferences.saveToPreferences();
142            pnlOAuthPreferences.saveToPreferences();
143        }
144    }
145
146    /**
147     * Listens to changes in the authentication method
148     */
149    class AuthenticationMethodChangeListener implements ItemListener {
150        @Override
151        public void itemStateChanged(ItemEvent e) {
152            if (rbBasicAuthentication.isSelected()) {
153                pnlAuthenticationParameters.removeAll();
154                pnlAuthenticationParameters.add(pnlBasicAuthPreferences, BorderLayout.CENTER);
155                pnlBasicAuthPreferences.revalidate();
156            } else {
157                pnlAuthenticationParameters.removeAll();
158                pnlAuthenticationParameters.add(pnlOAuthPreferences, BorderLayout.CENTER);
159                pnlOAuthPreferences.revalidate();
160            }
161            repaint();
162        }
163    }
164
165    @Override
166    public void propertyChange(PropertyChangeEvent evt) {
167        if (pnlOAuthPreferences != null) {
168            pnlOAuthPreferences.propertyChange(evt);
169        }
170    }
171}