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