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