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