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