source: josm/trunk/src/org/openstreetmap/josm/gui/oauth/AdvancedOAuthPropertiesPanel.java@ 19008

Last change on this file since 19008 was 19008, checked in by taylor.smock, 16 months ago

Fix an issue with custom OAuth2 parameters where the custom parameters would be replaced by default parameters

  • Property svn:eol-style set to native
File size: 11.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.oauth;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.Insets;
10import java.awt.event.ItemEvent;
11import java.awt.event.ItemListener;
12
13import javax.swing.BorderFactory;
14import javax.swing.JCheckBox;
15import javax.swing.JLabel;
16import javax.swing.JOptionPane;
17
18import org.openstreetmap.josm.data.oauth.IOAuthParameters;
19import org.openstreetmap.josm.data.oauth.OAuth20Parameters;
20import org.openstreetmap.josm.data.oauth.OAuthParameters;
21import org.openstreetmap.josm.data.oauth.OAuthVersion;
22import org.openstreetmap.josm.gui.HelpAwareOptionPane;
23import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
24import org.openstreetmap.josm.gui.MainApplication;
25import org.openstreetmap.josm.gui.help.HelpUtil;
26import org.openstreetmap.josm.gui.util.GuiHelper;
27import org.openstreetmap.josm.gui.widgets.JosmTextField;
28import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
29import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
30import org.openstreetmap.josm.spi.preferences.Config;
31import org.openstreetmap.josm.tools.CheckParameterUtil;
32import org.openstreetmap.josm.tools.ImageProvider;
33
34/**
35 * Panel allowing the user to setup advanced OAuth parameters:
36 * <ul>
37 * <li>Consumer key</li>
38 * <li>Consumer secret</li>
39 * <li>Request token URL</li>
40 * <li>Access token URL</li>
41 * <li>Authorize URL</li>
42 * <li>OSM login URL</li>
43 * <li>OSM logout URL</li>
44 * </ul>
45 *
46 * @see OAuthParameters
47 * @since 2746
48 */
49public class AdvancedOAuthPropertiesPanel extends VerticallyScrollablePanel {
50
51 private final JCheckBox cbUseDefaults = new JCheckBox(tr("Use default settings"));
52 private final JosmTextField tfConsumerKey = new JosmTextField();
53 private final JosmTextField tfConsumerSecret = new JosmTextField();
54 private final JosmTextField tfRequestTokenURL = new JosmTextField();
55 private final JosmTextField tfAccessTokenURL = new JosmTextField();
56 private final JosmTextField tfAuthoriseURL = new JosmTextField();
57 private final OAuthVersion oauthVersion;
58 private transient UseDefaultItemListener ilUseDefault;
59 private String apiUrl;
60
61 /**
62 * Constructs a new {@code AdvancedOAuthPropertiesPanel}.
63 * @param oauthVersion The OAuth version to make the panel for
64 */
65 public AdvancedOAuthPropertiesPanel(OAuthVersion oauthVersion) {
66 this.oauthVersion = oauthVersion;
67 build();
68 }
69
70 protected final void build() {
71 setLayout(new GridBagLayout());
72 setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
73 GridBagConstraints gc = new GridBagConstraints();
74
75 gc.anchor = GridBagConstraints.NORTHWEST;
76 gc.fill = GridBagConstraints.HORIZONTAL;
77 gc.weightx = 1.0;
78 gc.insets = new Insets(0, 0, 3, 3);
79 gc.gridwidth = 3;
80 add(cbUseDefaults, gc);
81
82 // -- consumer key
83 gc.gridy = 1;
84 gc.weightx = 0.0;
85 gc.gridwidth = 1;
86 add(new JLabel(tr("Client ID:")), gc);
87
88 gc.gridx = 1;
89 gc.weightx = 1.0;
90 add(tfConsumerKey, gc);
91 SelectAllOnFocusGainedDecorator.decorate(tfConsumerKey);
92
93 // -- consumer secret
94 gc.gridy++;
95 gc.gridx = 0;
96 gc.weightx = 0.0;
97 add(new JLabel(tr("Client Secret:")), gc);
98
99 gc.gridx = 1;
100 gc.weightx = 1.0;
101 add(tfConsumerSecret, gc);
102 SelectAllOnFocusGainedDecorator.decorate(tfConsumerSecret);
103
104 // -- request token URL
105 gc.gridy++;
106 gc.gridx = 0;
107 gc.weightx = 0.0;
108 add(new JLabel(tr("Redirect URL:")), gc);
109
110 gc.gridx = 1;
111 gc.weightx = 1.0;
112 add(tfRequestTokenURL, gc);
113 SelectAllOnFocusGainedDecorator.decorate(tfRequestTokenURL);
114
115 // -- access token URL
116 gc.gridy++;
117 gc.gridx = 0;
118 gc.weightx = 0.0;
119 add(new JLabel(tr("Access Token URL:")), gc);
120
121 gc.gridx = 1;
122 gc.weightx = 1.0;
123 add(tfAccessTokenURL, gc);
124 SelectAllOnFocusGainedDecorator.decorate(tfAccessTokenURL);
125
126 // -- authorise URL
127 gc.gridy++;
128 gc.gridx = 0;
129 gc.weightx = 0.0;
130 add(new JLabel(tr("Authorize URL:")), gc);
131
132 gc.gridx = 1;
133 gc.weightx = 1.0;
134 add(tfAuthoriseURL, gc);
135 SelectAllOnFocusGainedDecorator.decorate(tfAuthoriseURL);
136
137 ilUseDefault = new UseDefaultItemListener();
138 cbUseDefaults.addItemListener(ilUseDefault);
139 cbUseDefaults.setSelected(Config.getPref().getBoolean("oauth.settings.use-default", true));
140 }
141
142 protected boolean hasCustomSettings() {
143 IOAuthParameters params = OAuthParameters.createDefault(apiUrl, OAuthVersion.OAuth20);
144 return !params.equals(getAdvancedParameters());
145 }
146
147 protected boolean confirmOverwriteCustomSettings() {
148 ButtonSpec[] buttons = {
149 new ButtonSpec(
150 tr("Continue"),
151 new ImageProvider("ok"),
152 tr("Click to reset the OAuth settings to default values"),
153 null /* no dedicated help topic */
154 ),
155 new ButtonSpec(
156 tr("Cancel"),
157 new ImageProvider("cancel"),
158 tr("Click to abort resetting to the OAuth default values"),
159 null /* no dedicated help topic */
160 )
161 };
162 return 0 == HelpAwareOptionPane.showOptionDialog(
163 this,
164 tr(
165 "<html>JOSM is about to reset the OAuth settings to default values.<br>"
166 + "The current custom settings are not saved.</html>"
167 ),
168 tr("Overwrite custom OAuth settings?"),
169 JOptionPane.WARNING_MESSAGE,
170 null, /* no dedicated icon */
171 buttons,
172 buttons[0],
173 HelpUtil.ht("/Dialog/OAuthAuthorisationWizard")
174 );
175 }
176
177 protected void resetToDefaultSettings() {
178 IOAuthParameters iParams = OAuthParameters.createDefault(apiUrl, this.oauthVersion);
179 GuiHelper.runInEDTAndWaitWithException(() -> {
180 cbUseDefaults.setSelected(true);
181 switch (this.oauthVersion) {
182 case OAuth20:
183 case OAuth21:
184 OAuth20Parameters params20 = (OAuth20Parameters) iParams;
185 tfConsumerKey.setText(params20.getClientId());
186 tfConsumerSecret.setText(params20.getClientSecret());
187 tfAccessTokenURL.setText(params20.getAccessTokenUrl());
188 tfAuthoriseURL.setText(params20.getAuthorizationUrl());
189 tfRequestTokenURL.setText(params20.getRedirectUri());
190 break;
191 default:
192 throw new UnsupportedOperationException("Unsupported OAuth version: " + this.oauthVersion);
193 }
194 setChildComponentsEnabled(false);
195 });
196 }
197
198 protected void setChildComponentsEnabled(boolean enabled) {
199 for (Component c: getComponents()) {
200 if (c instanceof JosmTextField || c instanceof JLabel) {
201 c.setEnabled(enabled);
202 }
203 }
204 }
205
206 /**
207 * Replies the OAuth parameters currently edited in this properties panel.
208 *
209 * @return the OAuth parameters
210 */
211 public IOAuthParameters getAdvancedParameters() {
212 if (cbUseDefaults.isSelected())
213 return OAuthParameters.createDefault(apiUrl, this.oauthVersion);
214 return new OAuth20Parameters(
215 tfConsumerKey.getText(),
216 tfConsumerSecret.getText(),
217 tfAccessTokenURL.getText(),
218 tfAuthoriseURL.getText(),
219 apiUrl,
220 tfRequestTokenURL.getText()
221 );
222 }
223
224 /**
225 * Sets the advanced parameters to be displayed
226 *
227 * @param parameters the advanced parameters. Must not be null.
228 * @throws IllegalArgumentException if parameters is null.
229 */
230 public void setAdvancedParameters(IOAuthParameters parameters) {
231 CheckParameterUtil.ensureParameterNotNull(parameters, "parameters");
232 if (parameters.equals(OAuthParameters.createDefault(apiUrl, parameters.getOAuthVersion()))) {
233 cbUseDefaults.setSelected(true);
234 setChildComponentsEnabled(false);
235 } else {
236 cbUseDefaults.setSelected(false);
237 setChildComponentsEnabled(true);
238 if (parameters instanceof OAuth20Parameters) {
239 OAuth20Parameters parameters20 = (OAuth20Parameters) parameters;
240 tfConsumerKey.setText(parameters20.getClientId());
241 tfConsumerSecret.setText(parameters20.getClientSecret());
242 tfAccessTokenURL.setText(parameters20.getAccessTokenUrl());
243 tfAuthoriseURL.setText(parameters20.getAuthorizationUrl());
244 tfRequestTokenURL.setText(parameters20.getRedirectUri());
245 }
246 }
247 }
248
249 /**
250 * Initializes the panel from the values in the preferences <code>preferences</code>.
251 *
252 * @param paramApiUrl the API URL. Must not be null.
253 * @throws IllegalArgumentException if paramApiUrl is null
254 */
255 public void initialize(String paramApiUrl) {
256 CheckParameterUtil.ensureParameterNotNull(paramApiUrl, "paramApiUrl");
257 setApiUrl(paramApiUrl);
258 boolean useDefault = Config.getPref().getBoolean("oauth.settings.use-default", true);
259 ilUseDefault.setEnabled(false);
260 MainApplication.worker.execute(() -> {
261 if (useDefault) {
262 this.resetToDefaultSettings();
263 } else {
264 // createFromApiUrl may make a network request
265 final IOAuthParameters parameters = OAuthParameters.createFromApiUrl(paramApiUrl, OAuthVersion.OAuth20);
266 GuiHelper.runInEDT(() -> setAdvancedParameters(parameters));
267 }
268 GuiHelper.runInEDT(() -> ilUseDefault.setEnabled(true));
269 });
270 }
271
272 /**
273 * Remembers the current values in the preferences <code>pref</code>.
274 */
275 public void rememberPreferences() {
276 Config.getPref().putBoolean("oauth.settings.use-default", cbUseDefaults.isSelected());
277 if (cbUseDefaults.isSelected()) {
278 MainApplication.worker.execute(() -> OAuthParameters.createDefault().rememberPreferences());
279 } else {
280 getAdvancedParameters().rememberPreferences();
281 }
282 }
283
284 class UseDefaultItemListener implements ItemListener {
285 private boolean enabled;
286
287 @Override
288 public void itemStateChanged(ItemEvent e) {
289 if (!enabled) return;
290 switch (e.getStateChange()) {
291 case ItemEvent.SELECTED:
292 if (hasCustomSettings() && !confirmOverwriteCustomSettings()) {
293 cbUseDefaults.setSelected(false);
294 return;
295 }
296 MainApplication.worker.execute(AdvancedOAuthPropertiesPanel.this::resetToDefaultSettings);
297 break;
298 case ItemEvent.DESELECTED:
299 setChildComponentsEnabled(true);
300 break;
301 default: // Do nothing
302 }
303 }
304
305 public void setEnabled(boolean enabled) {
306 this.enabled = enabled;
307 }
308 }
309
310 /**
311 * Sets the URL of the OSM API for which this panel is currently displaying OAuth properties.
312 *
313 * @param apiUrl the api URL
314 * @since 5422
315 */
316 public void setApiUrl(String apiUrl) {
317 this.apiUrl = apiUrl;
318 if (cbUseDefaults.isSelected()) {
319 MainApplication.worker.execute(this::resetToDefaultSettings);
320 }
321 }
322}
Note: See TracBrowser for help on using the repository browser.