QGIS API Documentation  3.2.0-Bonn (bc43194)
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 
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() : QLatin1String( "" ) );
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 }
96 
97 void QgsAuthConfigEdit::populateAuthMethods()
98 {
99  QStringList authMethodKeys = QgsApplication::authManager()->authMethodsKeys( mDataProvider );
100 
101  // sort by auth method description attribute, then populate
102  QMap<QString, QgsAuthMethod *> descmap;
103  Q_FOREACH ( const QString &authMethodKey, authMethodKeys )
104  {
105  QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
106  if ( !authmethod )
107  {
108  QgsDebugMsg( QString( "Load auth method instance FAILED for auth method key (%1)" ).arg( authMethodKey ) );
109  continue;
110  }
111  descmap.insert( authmethod->displayDescription(), authmethod );
112  }
113 
114  QMap<QString, QgsAuthMethod *>::iterator it = descmap.begin();
115  for ( it = descmap.begin(); it != descmap.end(); ++it )
116  {
117  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>(
118  QgsApplication::authManager()->authMethodEditWidget( it.value()->key(), this ) );
119  if ( !editWidget )
120  {
121  QgsDebugMsg( QString( "Load auth method edit widget FAILED for auth method key (%1)" ).arg( it.value()->key() ) );
122  continue;
123  }
124  connect( editWidget, &QgsAuthMethodEdit::validityChanged, this, &QgsAuthConfigEdit::validateAuth );
125 
126  cmbAuthMethods->addItem( it.key(), QVariant( it.value()->key() ) );
127  stkwAuthMethods->addWidget( editWidget );
128  }
129 }
130 
131 void QgsAuthConfigEdit::loadConfig()
132 {
133  bool emptyAuthCfg = mAuthCfg.isEmpty();
134  authCfgEdit->setAllowEmptyId( emptyAuthCfg );
135  if ( emptyAuthCfg )
136  {
137  return;
138  }
139 
140  // edit mode requires master password to have been set and verified against auth db
141  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
142  {
143  mAuthCfg.clear();
144  return;
145  }
146 
147  QgsAuthMethodConfig mconfig;
148  if ( !QgsApplication::authManager()->loadAuthenticationConfig( mAuthCfg, mconfig, true ) )
149  {
150  QgsDebugMsg( QString( "Loading FAILED for authcfg: %1" ).arg( mAuthCfg ) );
151  return;
152  }
153 
154  if ( !mconfig.isValid( true ) )
155  {
156  QgsDebugMsg( QString( "Loading FAILED for authcfg (%1): invalid config" ).arg( mAuthCfg ) );
157  return;
158  }
159 
160  // load basic info
161  leName->setText( mconfig.name() );
162  leResource->setText( mconfig.uri() );
163  authCfgEdit->setAuthConfigId( mconfig.id() );
164 
165  QString authMethodKey = QgsApplication::authManager()->configAuthMethodKey( mAuthCfg );
166 
167  QgsDebugMsg( QString( "Loading authcfg: %1" ).arg( mAuthCfg ) );
168  QgsDebugMsg( QString( "Loading auth method: %1" ).arg( authMethodKey ) );
169 
170  if ( authMethodKey.isEmpty() )
171  {
172  QgsDebugMsg( QString( "Loading FAILED for authcfg (%1): no auth method found" ).arg( mAuthCfg ) );
173  return;
174  }
175 
176  if ( mconfig.method() != authMethodKey )
177  {
178  QgsDebugMsg( QString( "Loading FAILED for authcfg (%1): auth method and key mismatch" ).arg( mAuthCfg ) );
179  return;
180  }
181 
182  int indx = authMethodIndex( authMethodKey );
183  if ( indx == -1 )
184  {
185  QgsDebugMsg( QString( "Loading FAILED for authcfg (%1): no edit widget loaded for auth method '%2'" )
186  .arg( mAuthCfg, authMethodKey ) );
187  if ( cmbAuthMethods->count() > 0 )
188  {
189  cmbAuthMethods->setCurrentIndex( 0 );
190  stkwAuthMethods->setCurrentIndex( 0 );
191  }
192  return;
193  }
194 
195  cmbAuthMethods->setCurrentIndex( indx );
196  stkwAuthMethods->setCurrentIndex( indx );
197 
198  QgsAuthMethodEdit *editWidget = currentEditWidget();
199  if ( !editWidget )
200  {
201  QgsDebugMsg( QString( "Cast to edit widget FAILED for authcfg (%1) and auth method key (%2)" )
202  .arg( mAuthCfg, authMethodKey ) );
203  return;
204  }
205 
206  editWidget->loadConfig( mconfig.configMap() );
207 }
208 
209 void QgsAuthConfigEdit::resetConfig()
210 {
211  clearAll();
212  loadConfig();
213  validateAuth();
214 }
215 
216 void QgsAuthConfigEdit::saveConfig()
217 {
218  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
219  return;
220 
221  QString authMethodKey = cmbAuthMethods->currentData().toString();
222 
223  QgsAuthMethodEdit *editWidget = currentEditWidget();
224  if ( !editWidget )
225  {
226  QgsDebugMsg( QString( "Cast to edit widget FAILED)" ) );
227  return;
228  }
229 
230  QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
231  if ( !authmethod )
232  {
233  QgsDebugMsg( QString( "Save auth config FAILED when loading auth method instance from key (%1)" ).arg( authMethodKey ) );
234  return;
235  }
236 
237  QgsAuthMethodConfig mconfig;
238  mconfig.setName( leName->text() );
239  mconfig.setUri( leResource->text() );
240  mconfig.setMethod( authMethodKey );
241  mconfig.setVersion( authmethod->version() );
242  mconfig.setConfigMap( editWidget->configMap() );
243 
244  if ( !mconfig.isValid() )
245  {
246  QgsDebugMsg( "Save auth config FAILED: config invalid" );
247  return;
248  }
249 
250  QString authCfgId( authCfgEdit->configId() );
251  if ( !mAuthCfg.isEmpty() )
252  {
253  if ( authCfgId == mAuthCfg ) // update
254  {
255  mconfig.setId( mAuthCfg );
256  if ( QgsApplication::authManager()->updateAuthenticationConfig( mconfig ) )
257  {
258  emit authenticationConfigUpdated( mAuthCfg );
259  }
260  else
261  {
262  QgsDebugMsg( QString( "Updating auth config FAILED for authcfg: %1" ).arg( mAuthCfg ) );
263  }
264  }
265  else // store new with unique ID, then delete previous
266  {
267  mconfig.setId( authCfgId );
268  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
269  {
270  emit authenticationConfigStored( authCfgId );
271  if ( !QgsApplication::authManager()->removeAuthenticationConfig( mAuthCfg ) )
272  {
273  QgsDebugMsg( QString( "Removal of older auth config FAILED" ) );
274  }
275  mAuthCfg = authCfgId;
276  }
277  else
278  {
279  QgsDebugMsg( QString( "Storing new auth config with user-created unique ID FAILED" ) );
280  }
281  }
282  }
283  else if ( mAuthCfg.isEmpty() )
284  {
285  if ( authCfgId.isEmpty() ) // create new with generated ID
286  {
288  {
289  mAuthCfg = mconfig.id();
290  emit authenticationConfigStored( mAuthCfg );
291  }
292  else
293  {
294  QgsDebugMsg( QString( "Storing new auth config FAILED" ) );
295  }
296  }
297  else // create new with user-created unique ID
298  {
299  mconfig.setId( authCfgId );
300  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
301  {
302  mAuthCfg = authCfgId;
303  emit authenticationConfigStored( mAuthCfg );
304  }
305  else
306  {
307  QgsDebugMsg( QString( "Storing new auth config with user-created unique ID FAILED" ) );
308  }
309  }
310  }
311 
312  this->accept();
313 }
314 
315 void QgsAuthConfigEdit::btnClear_clicked()
316 {
317  QgsAuthMethodEdit *editWidget = currentEditWidget();
318  if ( !editWidget )
319  {
320  QgsDebugMsg( QString( "Cast to edit widget FAILED)" ) );
321  return;
322  }
323 
324  editWidget->clearConfig();
325 
326  validateAuth();
327 }
328 
329 void QgsAuthConfigEdit::clearAll()
330 {
331  leName->clear();
332  leResource->clear();
333  authCfgEdit->clear();
334 
335  for ( int i = 0; i < stkwAuthMethods->count(); i++ )
336  {
337  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->widget( i ) );
338  if ( editWidget )
339  {
340  editWidget->clearConfig();
341  }
342  }
343 
344  validateAuth();
345 }
346 
347 void QgsAuthConfigEdit::validateAuth()
348 {
349  bool authok = !leName->text().isEmpty();
350 
351  QgsAuthMethodEdit *editWidget = currentEditWidget();
352  if ( !editWidget )
353  {
354  QgsDebugMsg( QString( "Cast to edit widget FAILED" ) );
355  }
356  else
357  {
358  authok = authok && editWidget->validateConfig();
359  }
360  authok = authok && authCfgEdit->validate();
361 
362  buttonBox->button( QDialogButtonBox::Save )->setEnabled( authok );
363 }
364 
365 void QgsAuthConfigEdit::leName_textChanged( const QString &txt )
366 {
367  Q_UNUSED( txt );
368  validateAuth();
369 }
370 
371 int QgsAuthConfigEdit::authMethodIndex( const QString &authMethodKey )
372 {
373  return cmbAuthMethods->findData( QVariant( authMethodKey ) );
374 }
375 
376 QgsAuthMethodEdit *QgsAuthConfigEdit::currentEditWidget()
377 {
378  return qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->currentWidget() );
379 }
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.
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