001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.preferences.server;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.BorderLayout;
007 import java.awt.Color;
008 import java.awt.FlowLayout;
009 import java.awt.Font;
010 import java.awt.GridBagConstraints;
011 import java.awt.GridBagLayout;
012 import java.awt.Insets;
013 import java.awt.event.ActionEvent;
014 import java.awt.event.ItemEvent;
015 import java.awt.event.ItemListener;
016 import java.beans.PropertyChangeEvent;
017 import java.beans.PropertyChangeListener;
018
019 import javax.swing.AbstractAction;
020 import javax.swing.BorderFactory;
021 import javax.swing.JCheckBox;
022 import javax.swing.JLabel;
023 import javax.swing.JPanel;
024 import javax.swing.JTextField;
025
026 import org.openstreetmap.josm.Main;
027 import org.openstreetmap.josm.data.oauth.OAuthParameters;
028 import org.openstreetmap.josm.data.oauth.OAuthToken;
029 import org.openstreetmap.josm.gui.JMultilineLabel;
030 import org.openstreetmap.josm.gui.SideButton;
031 import org.openstreetmap.josm.gui.oauth.AdvancedOAuthPropertiesPanel;
032 import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard;
033 import org.openstreetmap.josm.gui.oauth.TestAccessTokenTask;
034 import org.openstreetmap.josm.io.auth.CredentialsManager;
035 import org.openstreetmap.josm.tools.ImageProvider;
036
037 /**
038 * The preferences panel for the OAuth preferences. This just a summary panel
039 * showing the current Access Token Key and Access Token Secret, if the
040 * user already has an Access Token.
041 *
042 * For initial authorisation see {@link OAuthAuthorizationWizard}.
043 *
044 */
045 public class OAuthAuthenticationPreferencesPanel extends JPanel implements PropertyChangeListener {
046 private JPanel pnlAuthorisationMessage;
047 private NotYetAuthorisedPanel pnlNotYetAuthorised;
048 private AlreadyAuthorisedPanel pnlAlreadyAuthorised;
049 private AdvancedOAuthPropertiesPanel pnlAdvancedProperties;
050 private String apiUrl;
051 private JCheckBox cbShowAdvancedParameters;
052 private JCheckBox cbSaveToPreferences;
053
054 /**
055 * Builds the panel for entering the advanced OAuth parameters
056 *
057 * @return
058 */
059 protected JPanel buildAdvancedPropertiesPanel() {
060 JPanel pnl = new JPanel(new GridBagLayout());
061 GridBagConstraints gc= new GridBagConstraints();
062
063 gc.anchor = GridBagConstraints.NORTHWEST;
064 gc.fill = GridBagConstraints.HORIZONTAL;
065 gc.weightx = 0.0;
066 gc.insets = new Insets(0,0,0,3);
067 pnl.add(cbShowAdvancedParameters = new JCheckBox(), gc);
068 cbShowAdvancedParameters.setSelected(false);
069 cbShowAdvancedParameters.addItemListener(
070 new ItemListener() {
071 public void itemStateChanged(ItemEvent evt) {
072 pnlAdvancedProperties.setVisible(evt.getStateChange() == ItemEvent.SELECTED);
073 }
074 }
075 );
076
077 gc.gridx = 1;
078 gc.weightx = 1.0;
079 JMultilineLabel lbl = new JMultilineLabel(tr("Display Advanced OAuth Parameters"));
080 lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
081 pnl.add(lbl, gc);
082
083 gc.gridy = 1;
084 gc.gridx = 1;
085 gc.insets = new Insets(3,0,3,0);
086 gc.fill = GridBagConstraints.BOTH;
087 gc.weightx = 1.0;
088 gc.weighty = 1.0;
089 pnl.add(pnlAdvancedProperties = new AdvancedOAuthPropertiesPanel(), gc);
090 pnlAdvancedProperties.initFromPreferences(Main.pref);
091 pnlAdvancedProperties.setBorder(
092 BorderFactory.createCompoundBorder(
093 BorderFactory.createLineBorder(Color.GRAY, 1),
094 BorderFactory.createEmptyBorder(3,3,3,3)
095 )
096 );
097 pnlAdvancedProperties.setVisible(false);
098 return pnl;
099 }
100
101 /**
102 * builds the UI
103 */
104 protected void build() {
105 setLayout(new GridBagLayout());
106 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
107 GridBagConstraints gc = new GridBagConstraints();
108
109 // the panel for the OAuth parameters. pnlAuthorisationMessage is an
110 // empty panel. It is going to be filled later, depending on the
111 // current OAuth state in JOSM.
112 gc.fill = GridBagConstraints.BOTH;
113 gc.anchor = GridBagConstraints.NORTHWEST;
114 gc.weighty = 1.0;
115 gc.weightx = 1.0;
116 gc.insets = new Insets(10,0,0,0);
117 add(pnlAuthorisationMessage = new JPanel(), gc);
118 pnlAuthorisationMessage.setLayout(new BorderLayout());
119
120 // create these two panels, they are going to be used later in refreshView
121 //
122 pnlAlreadyAuthorised = new AlreadyAuthorisedPanel();
123 pnlNotYetAuthorised = new NotYetAuthorisedPanel();
124 }
125
126 protected void refreshView() {
127 pnlAuthorisationMessage.removeAll();
128 if (OAuthAccessTokenHolder.getInstance().containsAccessToken()) {
129 pnlAuthorisationMessage.add(pnlAlreadyAuthorised, BorderLayout.CENTER);
130 pnlAlreadyAuthorised.refreshView();
131 pnlAlreadyAuthorised.revalidate();
132 } else {
133 pnlAuthorisationMessage.add(pnlNotYetAuthorised, BorderLayout.CENTER);
134 pnlNotYetAuthorised.revalidate();
135 }
136 repaint();
137 }
138
139 /**
140 * Create the panel
141 */
142 public OAuthAuthenticationPreferencesPanel() {
143 build();
144 refreshView();
145 }
146
147 /**
148 * Sets the URL of the OSM API for which this panel is currently displaying OAuth properties.
149 *
150 * @param apiUrl the api URL
151 */
152 public void setApiUrl(String apiUrl) {
153 this.apiUrl = apiUrl;
154 pnlAdvancedProperties.setApiUrl(apiUrl);
155 }
156
157 /**
158 * Initializes the panel from preferences
159 */
160 public void initFromPreferences() {
161 refreshView();
162 }
163
164 /**
165 * Saves the current values to preferences
166 */
167 public void saveToPreferences() {
168 OAuthAccessTokenHolder.getInstance().setSaveToPreferences(cbSaveToPreferences.isSelected());
169 OAuthAccessTokenHolder.getInstance().save(Main.pref, CredentialsManager.getInstance());
170 pnlAdvancedProperties.getAdvancedParameters().saveToPreferences(Main.pref);
171 }
172
173 /**
174 * The preferences panel displayed if there is currently no Access Token available.
175 * This means that the user didn't run through the OAuth authorisation procedure yet.
176 *
177 */
178 private class NotYetAuthorisedPanel extends JPanel {
179 protected void build() {
180 setLayout(new GridBagLayout());
181 GridBagConstraints gc = new GridBagConstraints();
182
183 // A message explaining that the user isn't authorised yet
184 gc.anchor = GridBagConstraints.NORTHWEST;
185 gc.insets = new Insets(0,0,3,0);
186 gc.fill = GridBagConstraints.HORIZONTAL;
187 gc.weightx = 1.0;
188 JLabel lbl;
189 add(lbl = new JMultilineLabel(tr("You do not have an Access Token yet to access the OSM server using OAuth. Please authorize first.")), gc);
190 lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
191
192 // Action for authorising now
193 gc.gridy = 1;
194 gc.fill = GridBagConstraints.NONE;
195 gc.weightx = 0.0;
196 add(new SideButton(new AuthoriseNowAction()), gc);
197
198 // filler - grab remaining space
199 gc.gridy = 2;
200 gc.fill = GridBagConstraints.BOTH;
201 gc.weightx = 1.0;
202 gc.weighty = 1.0;
203 add(new JPanel(), gc);
204 }
205
206 public NotYetAuthorisedPanel() {
207 build();
208 }
209 }
210
211 /**
212 * The preferences panel displayed if there is currently an AccessToken available.
213 *
214 */
215 private class AlreadyAuthorisedPanel extends JPanel {
216 private JTextField tfAccessTokenKey;
217 private JTextField tfAccessTokenSecret;
218
219 protected void build() {
220 setLayout(new GridBagLayout());
221 GridBagConstraints gc = new GridBagConstraints();
222 gc.anchor = GridBagConstraints.NORTHWEST;
223 gc.insets = new Insets(0,0,3,3);
224 gc.fill = GridBagConstraints.HORIZONTAL;
225 gc.weightx = 1.0;
226 gc.gridwidth = 2;
227 JLabel lbl;
228 add(lbl = new JMultilineLabel(tr("You already have an Access Token to access the OSM server using OAuth.")), gc);
229 lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
230
231 // -- access token key
232 gc.gridy = 1;
233 gc.gridx = 0;
234 gc.gridwidth = 1;
235 gc.weightx = 0.0;
236 add(new JLabel(tr("Access Token Key:")), gc);
237
238 gc.gridx = 1;
239 gc.weightx = 1.0;
240 add(tfAccessTokenKey = new JTextField(), gc);
241 tfAccessTokenKey.setEditable(false);
242
243 // -- access token secret
244 gc.gridy = 2;
245 gc.gridx = 0;
246 gc.gridwidth = 1;
247 gc.weightx = 0.0;
248 add(new JLabel(tr("Access Token Secret:")), gc);
249
250 gc.gridx = 1;
251 gc.weightx = 1.0;
252 add(tfAccessTokenSecret = new JTextField(), gc);
253 tfAccessTokenSecret.setEditable(false);
254
255 // -- access token secret
256 gc.gridy = 3;
257 gc.gridx = 0;
258 gc.gridwidth = 2;
259 gc.weightx = 1.0;
260 add(cbSaveToPreferences = new JCheckBox(tr("Save to preferences")), gc);
261 cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences());
262
263 // -- action buttons
264 JPanel btns = new JPanel(new FlowLayout(FlowLayout.LEFT));
265 btns.add(new SideButton(new RenewAuthorisationAction()));
266 btns.add(new SideButton(new TestAuthorisationAction()));
267 gc.gridy = 4;
268 gc.gridx = 0;
269 gc.gridwidth = 2;
270 gc.weightx = 1.0;
271 add(btns, gc);
272
273 // the panel with the advanced options
274 gc.gridy = 5;
275 gc.gridx = 0;
276 gc.gridwidth = 2;
277 gc.weightx = 1.0;
278 add(buildAdvancedPropertiesPanel(), gc);
279
280 // filler - grab the remaining space
281 gc.gridy = 6;
282 gc.fill = GridBagConstraints.BOTH;
283 gc.weightx = 1.0;
284 gc.weighty = 1.0;
285 add(new JPanel(), gc);
286
287 }
288
289 public void refreshView() {
290 String v = OAuthAccessTokenHolder.getInstance().getAccessTokenKey();
291 tfAccessTokenKey.setText(v == null? "" : v);
292 v = OAuthAccessTokenHolder.getInstance().getAccessTokenSecret();
293 tfAccessTokenSecret.setText(v == null? "" : v);
294 cbSaveToPreferences.setSelected(OAuthAccessTokenHolder.getInstance().isSaveToPreferences());
295 }
296
297 public AlreadyAuthorisedPanel() {
298 build();
299 refreshView();
300 }
301 }
302
303 /**
304 * Action to authorise the current user
305 */
306 private class AuthoriseNowAction extends AbstractAction {
307 public AuthoriseNowAction() {
308 putValue(NAME, tr("Authorize now"));
309 putValue(SHORT_DESCRIPTION, tr("Click to step through the OAuth authorization process"));
310 putValue(SMALL_ICON, ImageProvider.get("oauth", "oauth"));
311
312 }
313 public void actionPerformed(ActionEvent arg0) {
314 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
315 OAuthAuthenticationPreferencesPanel.this,
316 apiUrl
317 );
318 wizard.setVisible(true);
319 if (wizard.isCanceled()) return;
320 OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
321 holder.setAccessToken(wizard.getAccessToken());
322 holder.setSaveToPreferences(wizard.isSaveAccessTokenToPreferences());
323 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters());
324 refreshView();
325 }
326 }
327
328 /**
329 * Launches the OAuthAuthorisationWizard to generate a new Access Token
330 */
331 private class RenewAuthorisationAction extends AbstractAction {
332 public RenewAuthorisationAction() {
333 putValue(NAME, tr("New Access Token"));
334 putValue(SHORT_DESCRIPTION, tr("Click to step through the OAuth authorization process and generate a new Access Token"));
335 putValue(SMALL_ICON, ImageProvider.get("oauth", "oauth"));
336
337 }
338 public void actionPerformed(ActionEvent arg0) {
339 OAuthAuthorizationWizard wizard = new OAuthAuthorizationWizard(
340 OAuthAuthenticationPreferencesPanel.this,
341 apiUrl
342 );
343 wizard.setVisible(true);
344 if (wizard.isCanceled()) return;
345 OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
346 holder.setAccessToken(wizard.getAccessToken());
347 holder.setSaveToPreferences(wizard.isSaveAccessTokenToPreferences());
348 pnlAdvancedProperties.setAdvancedParameters(wizard.getOAuthParameters());
349 refreshView();
350 }
351 }
352
353 /**
354 * Runs a test whether we can access the OSM server with the current Access Token
355 */
356 private class TestAuthorisationAction extends AbstractAction {
357 public TestAuthorisationAction() {
358 putValue(NAME, tr("Test Access Token"));
359 putValue(SHORT_DESCRIPTION, tr("Click test access to the OSM server with the current access token"));
360 putValue(SMALL_ICON, ImageProvider.get("oauth", "oauth"));
361
362 }
363
364 public void actionPerformed(ActionEvent evt) {
365 OAuthToken token = OAuthAccessTokenHolder.getInstance().getAccessToken();
366 OAuthParameters parameters = OAuthParameters.createFromPreferences(Main.pref);
367 TestAccessTokenTask task = new TestAccessTokenTask(
368 OAuthAuthenticationPreferencesPanel.this,
369 apiUrl,
370 parameters,
371 token
372 );
373 Main.worker.submit(task);
374 }
375 }
376
377 public void propertyChange(PropertyChangeEvent evt) {
378 if (! evt.getPropertyName().equals(OsmApiUrlInputPanel.API_URL_PROP))
379 return;
380 setApiUrl((String)evt.getNewValue());
381 }
382 }