QGIS API Documentation  3.6.0-Noosa (5873452)
qgsauthconfigedit.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsauthconfigedit.cpp
3  ---------------------
4  begin : September 1, 2015
5  copyright : (C) 2015 by Boundless Spatial, Inc. USA
6  author : Larry Shaffer
7  email : lshaffer at boundlessgeo dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgsauthconfigedit.h"
18 
19 #include <QPushButton>
20 
21 #include "qgsauthconfig.h"
22 #include "qgsauthconfigidedit.h"
23 #include "qgsauthmanager.h"
24 #include "qgsauthmethodedit.h"
25 #include "qgslogger.h"
26 #include "qgsapplication.h"
27 #include "qgsgui.h"
28 
29 QgsAuthConfigEdit::QgsAuthConfigEdit( QWidget *parent, const QString &authcfg, const QString &dataprovider )
30  : QDialog( parent )
31  , mAuthCfg( authcfg )
32  , mDataProvider( dataprovider )
33 
34 {
35  bool disabled = QgsApplication::authManager()->isDisabled();
36  bool idok = true;
37 
38  if ( !disabled && !authcfg.isEmpty() )
39  {
40  idok = QgsApplication::authManager()->configIds().contains( authcfg );
41  }
42 
43  if ( disabled || !idok )
44  {
45  mAuthNotifyLayout = new QVBoxLayout;
46  this->setLayout( mAuthNotifyLayout );
47 
48  QString msg( disabled ? QgsApplication::authManager()->disabledMessage() : QString() );
49  if ( !authcfg.isEmpty() )
50  {
51  msg += "\n\n" + tr( "Authentication config id not loaded: %1" ).arg( authcfg );
52  }
53  mAuthNotify = new QLabel( msg, this );
54  mAuthNotifyLayout->addWidget( mAuthNotify );
55 
56  mAuthCfg.clear(); // otherwise will contiue to try authenticate (and fail) after save
57  buttonBox->button( QDialogButtonBox::Save )->setEnabled( false );
58  }
59  else
60  {
61  setupUi( this );
62  connect( btnClear, &QToolButton::clicked, this, &QgsAuthConfigEdit::btnClear_clicked );
63  connect( leName, &QLineEdit::textChanged, this, &QgsAuthConfigEdit::leName_textChanged );
64  connect( buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close );
65  connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsAuthConfigEdit::saveConfig );
66  connect( buttonBox->button( QDialogButtonBox::Reset ), &QAbstractButton::clicked, this, &QgsAuthConfigEdit::resetConfig );
67 
68  populateAuthMethods();
69 
70  connect( cmbAuthMethods, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
71  stkwAuthMethods, &QStackedWidget::setCurrentIndex );
72  connect( cmbAuthMethods, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
73  this, [ = ] { validateAuth(); } );
74 
75  connect( authCfgEdit, &QgsAuthConfigIdEdit::validityChanged, this, &QgsAuthConfigEdit::validateAuth );
76 
77  // needed (if only combobox is ever changed)?
78  // connect( stkwAuthMethods, SIGNAL( currentChanged( int ) ),
79  // cmbAuthMethods, SLOT( setCurrentIndex( int ) ) );
80 
81  // connect( stkwAuthMethods, SIGNAL( currentChanged( int ) ),
82  // this, SLOT( validateAuth() ) );
83 
84  if ( cmbAuthMethods->count() > 0 )
85  {
86  cmbAuthMethods->setCurrentIndex( 0 );
87  stkwAuthMethods->setCurrentIndex( 0 );
88  }
89 
90  loadConfig();
91  validateAuth();
92 
93  leName->setFocus();
94  }
95 
97 }
98 
99 void QgsAuthConfigEdit::populateAuthMethods()
100 {
101  QStringList authMethodKeys = QgsApplication::authManager()->authMethodsKeys( mDataProvider );
102 
103  // sort by auth method description attribute, then populate
104  QMap<QString, QgsAuthMethod *> descmap;
105  Q_FOREACH ( const QString &authMethodKey, authMethodKeys )
106  {
107  QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
108  if ( !authmethod )
109  {
110  QgsDebugMsg( QStringLiteral( "Load auth method instance FAILED for auth method key (%1)" ).arg( authMethodKey ) );
111  continue;
112  }
113  descmap.insert( authmethod->displayDescription(), authmethod );
114  }
115 
116  QMap<QString, QgsAuthMethod *>::iterator it = descmap.begin();
117  for ( it = descmap.begin(); it != descmap.end(); ++it )
118  {
119  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>(
120  QgsApplication::authManager()->authMethodEditWidget( it.value()->key(), this ) );
121  if ( !editWidget )
122  {
123  QgsDebugMsg( QStringLiteral( "Load auth method edit widget FAILED for auth method key (%1)" ).arg( it.value()->key() ) );
124  continue;
125  }
126  connect( editWidget, &QgsAuthMethodEdit::validityChanged, this, &QgsAuthConfigEdit::validateAuth );
127 
128  cmbAuthMethods->addItem( it.key(), QVariant( it.value()->key() ) );
129  stkwAuthMethods->addWidget( editWidget );
130  }
131 }
132 
133 void QgsAuthConfigEdit::loadConfig()
134 {
135  bool emptyAuthCfg = mAuthCfg.isEmpty();
136  authCfgEdit->setAllowEmptyId( emptyAuthCfg );
137  if ( emptyAuthCfg )
138  {
139  return;
140  }
141 
142  // edit mode requires master password to have been set and verified against auth db
143  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
144  {
145  mAuthCfg.clear();
146  return;
147  }
148 
149  QgsAuthMethodConfig mconfig;
150  if ( !QgsApplication::authManager()->loadAuthenticationConfig( mAuthCfg, mconfig, true ) )
151  {
152  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg: %1" ).arg( mAuthCfg ) );
153  return;
154  }
155 
156  if ( !mconfig.isValid( true ) )
157  {
158  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): invalid config" ).arg( mAuthCfg ) );
159  return;
160  }
161 
162  // load basic info
163  leName->setText( mconfig.name() );
164  leResource->setText( mconfig.uri() );
165  authCfgEdit->setAuthConfigId( mconfig.id() );
166 
167  QString authMethodKey = QgsApplication::authManager()->configAuthMethodKey( mAuthCfg );
168 
169  QgsDebugMsg( QStringLiteral( "Loading authcfg: %1" ).arg( mAuthCfg ) );
170  QgsDebugMsg( QStringLiteral( "Loading auth method: %1" ).arg( authMethodKey ) );
171 
172  if ( authMethodKey.isEmpty() )
173  {
174  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): no auth method found" ).arg( mAuthCfg ) );
175  return;
176  }
177 
178  if ( mconfig.method() != authMethodKey )
179  {
180  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): auth method and key mismatch" ).arg( mAuthCfg ) );
181  return;
182  }
183 
184  int indx = authMethodIndex( authMethodKey );
185  if ( indx == -1 )
186  {
187  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): no edit widget loaded for auth method '%2'" )
188  .arg( mAuthCfg, authMethodKey ) );
189  if ( cmbAuthMethods->count() > 0 )
190  {
191  cmbAuthMethods->setCurrentIndex( 0 );
192  stkwAuthMethods->setCurrentIndex( 0 );
193  }
194  return;
195  }
196 
197  cmbAuthMethods->setCurrentIndex( indx );
198  stkwAuthMethods->setCurrentIndex( indx );
199 
200  QgsAuthMethodEdit *editWidget = currentEditWidget();
201  if ( !editWidget )
202  {
203  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED for authcfg (%1) and auth method key (%2)" )
204  .arg( mAuthCfg, authMethodKey ) );
205  return;
206  }
207 
208  editWidget->loadConfig( mconfig.configMap() );
209 }
210 
211 void QgsAuthConfigEdit::resetConfig()
212 {
213  clearAll();
214  loadConfig();
215  validateAuth();
216 }
217 
218 void QgsAuthConfigEdit::saveConfig()
219 {
220  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
221  return;
222 
223  QString authMethodKey = cmbAuthMethods->currentData().toString();
224 
225  QgsAuthMethodEdit *editWidget = currentEditWidget();
226  if ( !editWidget )
227  {
228  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED)" ) );
229  return;
230  }
231 
232  QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
233  if ( !authmethod )
234  {
235  QgsDebugMsg( QStringLiteral( "Save auth config FAILED when loading auth method instance from key (%1)" ).arg( authMethodKey ) );
236  return;
237  }
238 
239  QgsAuthMethodConfig mconfig;
240  mconfig.setName( leName->text() );
241  mconfig.setUri( leResource->text() );
242  mconfig.setMethod( authMethodKey );
243  mconfig.setVersion( authmethod->version() );
244  mconfig.setConfigMap( editWidget->configMap() );
245 
246  if ( !mconfig.isValid() )
247  {
248  QgsDebugMsg( QStringLiteral( "Save auth config FAILED: config invalid" ) );
249  return;
250  }
251 
252  QString authCfgId( authCfgEdit->configId() );
253  if ( !mAuthCfg.isEmpty() )
254  {
255  if ( authCfgId == mAuthCfg ) // update
256  {
257  mconfig.setId( mAuthCfg );
258  if ( QgsApplication::authManager()->updateAuthenticationConfig( mconfig ) )
259  {
260  emit authenticationConfigUpdated( mAuthCfg );
261  }
262  else
263  {
264  QgsDebugMsg( QStringLiteral( "Updating auth config FAILED for authcfg: %1" ).arg( mAuthCfg ) );
265  }
266  }
267  else // store new with unique ID, then delete previous
268  {
269  mconfig.setId( authCfgId );
270  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
271  {
272  emit authenticationConfigStored( authCfgId );
273  if ( !QgsApplication::authManager()->removeAuthenticationConfig( mAuthCfg ) )
274  {
275  QgsDebugMsg( QStringLiteral( "Removal of older auth config FAILED" ) );
276  }
277  mAuthCfg = authCfgId;
278  }
279  else
280  {
281  QgsDebugMsg( QStringLiteral( "Storing new auth config with user-created unique ID FAILED" ) );
282  }
283  }
284  }
285  else if ( mAuthCfg.isEmpty() )
286  {
287  if ( authCfgId.isEmpty() ) // create new with generated ID
288  {
290  {
291  mAuthCfg = mconfig.id();
292  emit authenticationConfigStored( mAuthCfg );
293  }
294  else
295  {
296  QgsDebugMsg( QStringLiteral( "Storing new auth config FAILED" ) );
297  }
298  }
299  else // create new with user-created unique ID
300  {
301  mconfig.setId( authCfgId );
302  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
303  {
304  mAuthCfg = authCfgId;
305  emit authenticationConfigStored( mAuthCfg );
306  }
307  else
308  {
309  QgsDebugMsg( QStringLiteral( "Storing new auth config with user-created unique ID FAILED" ) );
310  }
311  }
312  }
313 
314  this->accept();
315 }
316 
317 void QgsAuthConfigEdit::btnClear_clicked()
318 {
319  QgsAuthMethodEdit *editWidget = currentEditWidget();
320  if ( !editWidget )
321  {
322  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED)" ) );
323  return;
324  }
325 
326  editWidget->clearConfig();
327 
328  validateAuth();
329 }
330 
331 void QgsAuthConfigEdit::clearAll()
332 {
333  leName->clear();
334  leResource->clear();
335  authCfgEdit->clear();
336 
337  for ( int i = 0; i < stkwAuthMethods->count(); i++ )
338  {
339  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->widget( i ) );
340  if ( editWidget )
341  {
342  editWidget->clearConfig();
343  }
344  }
345 
346  validateAuth();
347 }
348 
349 void QgsAuthConfigEdit::validateAuth()
350 {
351  bool authok = !leName->text().isEmpty();
352 
353  QgsAuthMethodEdit *editWidget = currentEditWidget();
354  if ( !editWidget )
355  {
356  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED" ) );
357  }
358  else
359  {
360  authok = authok && editWidget->validateConfig();
361  }
362  authok = authok && authCfgEdit->validate();
363 
364  buttonBox->button( QDialogButtonBox::Save )->setEnabled( authok );
365 }
366 
367 void QgsAuthConfigEdit::leName_textChanged( const QString &txt )
368 {
369  Q_UNUSED( txt );
370  validateAuth();
371 }
372 
373 int QgsAuthConfigEdit::authMethodIndex( const QString &authMethodKey )
374 {
375  return cmbAuthMethods->findData( QVariant( authMethodKey ) );
376 }
377 
378 QgsAuthMethodEdit *QgsAuthConfigEdit::currentEditWidget()
379 {
380  return qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->currentWidget() );
381 }
virtual QgsStringMap configMap() const =0
The configuration key-vale map of subclasses.
void setUri(const QString &uri)
Definition: qgsauthconfig.h:70
QgsStringMap configMap() const
Gets extended configuration, mapped to key/value pairs of QStrings.
bool isValid(bool validateid=false) const
Whether the configuration is valid.
void setId(const QString &id)
Sets auth config ID.
Definition: qgsauthconfig.h:61
int version() const
Increment this if method is significantly updated, allow updater code to be written for previously st...
Definition: qgsauthmethod.h:72
void validityChanged(bool valid)
Validity of the ID has changed.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
void authenticationConfigUpdated(const QString &authcfg)
Emit current id when an existing config is updated in auth database.
Abstract base class for the edit widget of authentication method plugins.
QStringList authMethodsKeys(const QString &dataprovider=QString())
Gets keys of supported authentication methods.
QgsAuthMethod * authMethod(const QString &authMethodKey)
Gets authentication method from the config/provider cache via its key.
QgsAuthConfigEdit(QWidget *parent=nullptr, const QString &authcfg=QString(), const QString &dataprovider=QString())
Create a dialog for editing an authentication configuration.
virtual void clearConfig()=0
Clear GUI controls in subclassed widget.
virtual void loadConfig(const QgsStringMap &configmap)=0
Load an existing config map into subclassed widget.
void validityChanged(bool valid)
Emitted when the configuration validatity changes.
void setMethod(const QString &method)
Definition: qgsauthconfig.h:74
Configuration storage class for authentication method configurations.
Definition: qgsauthconfig.h:38
const QString name() const
Gets name of configuration.
Definition: qgsauthconfig.h:64
QStringList configIds() const
Gets list of authentication ids from database.
QWidget * authMethodEditWidget(const QString &authMethodKey, QWidget *parent)
Gets authentication method edit widget via its key.
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
QString configAuthMethodKey(const QString &authcfg) const
Gets key of authentication method associated with config ID.
virtual bool validateConfig()=0
Validate the configuration of subclasses.
Abstract base class for authentication method plugins.
Definition: qgsauthmethod.h:36
void authenticationConfigStored(const QString &authcfg)
Emit generated id when a new config is saved to auth database.
virtual QString displayDescription() const =0
Translatable display version of the &#39;description()&#39;.
bool storeAuthenticationConfig(QgsAuthMethodConfig &mconfig)
Store an authentication config in the database.
void setVersion(int version)
Sets version of the configuration.
Definition: qgsauthconfig.h:79
bool isDisabled() const
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:104
QString method() const
Textual key of the associated authentication method.
Definition: qgsauthconfig.h:73
const QString uri() const
A URI to auto-select a config when connecting to a resource.
Definition: qgsauthconfig.h:69
void setName(const QString &name)
Sets name of configuration.
Definition: qgsauthconfig.h:66
void setConfigMap(const QgsStringMap &map)
Set extended configuration map.
const QString id() const
Gets &#39;authcfg&#39; 7-character alphanumeric ID of the config.
Definition: qgsauthconfig.h:59