001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.oauth;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.awt.Insets;
010import java.awt.event.ItemEvent;
011import java.awt.event.ItemListener;
012
013import javax.swing.BorderFactory;
014import javax.swing.JCheckBox;
015import javax.swing.JLabel;
016import javax.swing.JOptionPane;
017
018import org.openstreetmap.josm.data.oauth.OAuthParameters;
019import org.openstreetmap.josm.gui.HelpAwareOptionPane;
020import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
021import org.openstreetmap.josm.gui.help.HelpUtil;
022import org.openstreetmap.josm.gui.widgets.JosmTextField;
023import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
024import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
025import org.openstreetmap.josm.spi.preferences.Config;
026import org.openstreetmap.josm.tools.CheckParameterUtil;
027import org.openstreetmap.josm.tools.ImageProvider;
028
029/**
030 * Panel allowing the user to setup advanced OAuth parameters:
031 * <ul>
032 * <li>Consumer key</li>
033 * <li>Consumer secret</li>
034 * <li>Request token URL</li>
035 * <li>Access token URL</li>
036 * <li>Authorize URL</li>
037 * <li>OSM login URL</li>
038 * <li>OSM logout URL</li>
039 * </ul>
040 *
041 * @see OAuthParameters
042 * @since 2746
043 */
044public class AdvancedOAuthPropertiesPanel extends VerticallyScrollablePanel {
045
046    private final JCheckBox cbUseDefaults = new JCheckBox(tr("Use default settings"));
047    private final JosmTextField tfConsumerKey = new JosmTextField();
048    private final JosmTextField tfConsumerSecret = new JosmTextField();
049    private final JosmTextField tfRequestTokenURL = new JosmTextField();
050    private final JosmTextField tfAccessTokenURL = new JosmTextField();
051    private final JosmTextField tfAuthoriseURL = new JosmTextField();
052    private final JosmTextField tfOsmLoginURL = new JosmTextField();
053    private final JosmTextField tfOsmLogoutURL = new JosmTextField();
054    private transient UseDefaultItemListener ilUseDefault;
055    private String apiUrl;
056
057    /**
058     * Constructs a new {@code AdvancedOAuthPropertiesPanel}.
059     */
060    public AdvancedOAuthPropertiesPanel() {
061        build();
062    }
063
064    protected final void build() {
065        setLayout(new GridBagLayout());
066        setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
067        GridBagConstraints gc = new GridBagConstraints();
068
069        gc.anchor = GridBagConstraints.NORTHWEST;
070        gc.fill = GridBagConstraints.HORIZONTAL;
071        gc.weightx = 1.0;
072        gc.insets = new Insets(0, 0, 3, 3);
073        gc.gridwidth = 2;
074        add(cbUseDefaults, gc);
075
076        // -- consumer key
077        gc.gridy = 1;
078        gc.weightx = 0.0;
079        gc.gridwidth = 1;
080        add(new JLabel(tr("Consumer Key:")), gc);
081
082        gc.gridx = 1;
083        gc.weightx = 1.0;
084        add(tfConsumerKey, gc);
085        SelectAllOnFocusGainedDecorator.decorate(tfConsumerKey);
086
087        // -- consumer secret
088        gc.gridy = 2;
089        gc.gridx = 0;
090        gc.weightx = 0.0;
091        add(new JLabel(tr("Consumer Secret:")), gc);
092
093        gc.gridx = 1;
094        gc.weightx = 1.0;
095        add(tfConsumerSecret, gc);
096        SelectAllOnFocusGainedDecorator.decorate(tfConsumerSecret);
097
098        // -- request token URL
099        gc.gridy = 3;
100        gc.gridx = 0;
101        gc.weightx = 0.0;
102        add(new JLabel(tr("Request Token URL:")), gc);
103
104        gc.gridx = 1;
105        gc.weightx = 1.0;
106        add(tfRequestTokenURL, gc);
107        SelectAllOnFocusGainedDecorator.decorate(tfRequestTokenURL);
108
109        // -- access token URL
110        gc.gridy = 4;
111        gc.gridx = 0;
112        gc.weightx = 0.0;
113        add(new JLabel(tr("Access Token URL:")), gc);
114
115        gc.gridx = 1;
116        gc.weightx = 1.0;
117        add(tfAccessTokenURL, gc);
118        SelectAllOnFocusGainedDecorator.decorate(tfAccessTokenURL);
119
120        // -- authorise URL
121        gc.gridy = 5;
122        gc.gridx = 0;
123        gc.weightx = 0.0;
124        add(new JLabel(tr("Authorize URL:")), gc);
125
126        gc.gridx = 1;
127        gc.weightx = 1.0;
128        add(tfAuthoriseURL, gc);
129        SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL);
130
131        // -- OSM login URL
132        gc.gridy = 6;
133        gc.gridx = 0;
134        gc.weightx = 0.0;
135        add(new JLabel(tr("OSM login URL:")), gc);
136
137        gc.gridx = 1;
138        gc.weightx = 1.0;
139        add(tfOsmLoginURL, gc);
140        SelectAllOnFocusGainedDecorator.decorate(tfOsmLoginURL);
141
142        // -- OSM logout URL
143        gc.gridy = 7;
144        gc.gridx = 0;
145        gc.weightx = 0.0;
146        add(new JLabel(tr("OSM logout URL:")), gc);
147
148        gc.gridx = 1;
149        gc.weightx = 1.0;
150        add(tfOsmLogoutURL, gc);
151        SelectAllOnFocusGainedDecorator.decorate(tfOsmLogoutURL);
152
153        ilUseDefault = new UseDefaultItemListener();
154        cbUseDefaults.addItemListener(ilUseDefault);
155    }
156
157    protected boolean hasCustomSettings() {
158        OAuthParameters params = OAuthParameters.createDefault(apiUrl);
159        return !params.equals(getAdvancedParameters());
160    }
161
162    protected boolean confirmOverwriteCustomSettings() {
163        ButtonSpec[] buttons = {
164                new ButtonSpec(
165                        tr("Continue"),
166                        new ImageProvider("ok"),
167                        tr("Click to reset the OAuth settings to default values"),
168                        null /* no dedicated help topic */
169                ),
170                new ButtonSpec(
171                        tr("Cancel"),
172                        new ImageProvider("cancel"),
173                        tr("Click to abort resetting to the OAuth default values"),
174                        null /* no dedicated help topic */
175                )
176        };
177        return 0 == HelpAwareOptionPane.showOptionDialog(
178                this,
179                tr(
180                        "<html>JOSM is about to reset the OAuth settings to default values.<br>"
181                        + "The current custom settings are not saved.</html>"
182                ),
183                tr("Overwrite custom OAuth settings?"),
184                JOptionPane.WARNING_MESSAGE,
185                null, /* no dedicated icon */
186                buttons,
187                buttons[0],
188                HelpUtil.ht("/Dialog/OAuthAuthorisationWizard")
189        );
190    }
191
192    protected void resetToDefaultSettings() {
193        cbUseDefaults.setSelected(true);
194        OAuthParameters params = OAuthParameters.createDefault(apiUrl);
195        tfConsumerKey.setText(params.getConsumerKey());
196        tfConsumerSecret.setText(params.getConsumerSecret());
197        tfRequestTokenURL.setText(params.getRequestTokenUrl());
198        tfAccessTokenURL.setText(params.getAccessTokenUrl());
199        tfAuthoriseURL.setText(params.getAuthoriseUrl());
200        tfOsmLoginURL.setText(params.getOsmLoginUrl());
201        tfOsmLogoutURL.setText(params.getOsmLogoutUrl());
202
203        setChildComponentsEnabled(false);
204    }
205
206    protected void setChildComponentsEnabled(boolean enabled) {
207        for (Component c: getComponents()) {
208            if (c instanceof JosmTextField || c instanceof JLabel) {
209                c.setEnabled(enabled);
210            }
211        }
212    }
213
214    /**
215     * Replies the OAuth parameters currently edited in this properties panel.
216     *
217     * @return the OAuth parameters
218     */
219    public OAuthParameters getAdvancedParameters() {
220        if (cbUseDefaults.isSelected())
221            return OAuthParameters.createDefault(apiUrl);
222        return new OAuthParameters(
223            tfConsumerKey.getText(),
224            tfConsumerSecret.getText(),
225            tfRequestTokenURL.getText(),
226            tfAccessTokenURL.getText(),
227            tfAuthoriseURL.getText(),
228            tfOsmLoginURL.getText(),
229            tfOsmLogoutURL.getText());
230    }
231
232    /**
233     * Sets the advanced parameters to be displayed
234     *
235     * @param parameters the advanced parameters. Must not be null.
236     * @throws IllegalArgumentException if parameters is null.
237     */
238    public void setAdvancedParameters(OAuthParameters parameters) {
239        CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
240        if (parameters.equals(OAuthParameters.createDefault(apiUrl))) {
241            cbUseDefaults.setSelected(true);
242            setChildComponentsEnabled(false);
243        } else {
244            cbUseDefaults.setSelected(false);
245            setChildComponentsEnabled(true);
246            tfConsumerKey.setText(parameters.getConsumerKey() == null ? "" : parameters.getConsumerKey());
247            tfConsumerSecret.setText(parameters.getConsumerSecret() == null ? "" : parameters.getConsumerSecret());
248            tfRequestTokenURL.setText(parameters.getRequestTokenUrl() == null ? "" : parameters.getRequestTokenUrl());
249            tfAccessTokenURL.setText(parameters.getAccessTokenUrl() == null ? "" : parameters.getAccessTokenUrl());
250            tfAuthoriseURL.setText(parameters.getAuthoriseUrl() == null ? "" : parameters.getAuthoriseUrl());
251            tfOsmLoginURL.setText(parameters.getOsmLoginUrl() == null ? "" : parameters.getOsmLoginUrl());
252            tfOsmLogoutURL.setText(parameters.getOsmLogoutUrl() == null ? "" : parameters.getOsmLogoutUrl());
253        }
254    }
255
256    /**
257     * Initializes the panel from the values in the preferences <code>preferences</code>.
258     *
259     * @param paramApiUrl the API URL. Must not be null.
260     * @throws IllegalArgumentException if paramApiUrl is null
261     */
262    public void initialize(String paramApiUrl) {
263        CheckParameterUtil.ensureParameterNotNull(paramApiUrl, "paramApiUrl");
264        setApiUrl(paramApiUrl);
265        boolean useDefault = Config.getPref().getBoolean("oauth.settings.use-default", true);
266        ilUseDefault.setEnabled(false);
267        if (useDefault) {
268            resetToDefaultSettings();
269        } else {
270            setAdvancedParameters(OAuthParameters.createFromApiUrl(paramApiUrl));
271        }
272        ilUseDefault.setEnabled(true);
273    }
274
275    /**
276     * Remembers the current values in the preferences <code>pref</code>.
277     */
278    public void rememberPreferences() {
279        Config.getPref().putBoolean("oauth.settings.use-default", cbUseDefaults.isSelected());
280        if (cbUseDefaults.isSelected()) {
281            new OAuthParameters(null, null, null, null, null, null, null).rememberPreferences();
282        } else {
283            getAdvancedParameters().rememberPreferences();
284        }
285    }
286
287    class UseDefaultItemListener implements ItemListener {
288        private boolean enabled;
289
290        @Override
291        public void itemStateChanged(ItemEvent e) {
292            if (!enabled) return;
293            switch (e.getStateChange()) {
294            case ItemEvent.SELECTED:
295                if (hasCustomSettings() && !confirmOverwriteCustomSettings()) {
296                    cbUseDefaults.setSelected(false);
297                    return;
298                }
299                resetToDefaultSettings();
300                break;
301            case ItemEvent.DESELECTED:
302                setChildComponentsEnabled(true);
303                break;
304            default: // Do nothing
305            }
306        }
307
308        public void setEnabled(boolean enabled) {
309            this.enabled = enabled;
310        }
311    }
312
313    /**
314     * Sets the URL of the OSM API for which this panel is currently displaying OAuth properties.
315     *
316     * @param apiUrl the api URL
317     * @since 5422
318     */
319    public void setApiUrl(String apiUrl) {
320        this.apiUrl = apiUrl;
321        if (cbUseDefaults.isSelected()) {
322            resetToDefaultSettings();
323        }
324    }
325}