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 }