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, 3 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.