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