QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 continue 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  const auto constAuthMethodKeys = authMethodKeys;
106  for ( const QString &authMethodKey : constAuthMethodKeys )
107  {
108  QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
109  if ( !authmethod )
110  {
111  QgsDebugMsg( QStringLiteral( "Load auth method instance FAILED for auth method key (%1)" ).arg( authMethodKey ) );
112  continue;
113  }
114  descmap.insert( authmethod->displayDescription(), authmethod );
115  }
116 
117  QMap<QString, QgsAuthMethod *>::iterator it = descmap.begin();
118  for ( it = descmap.begin(); it != descmap.end(); ++it )
119  {
120  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>(
121  QgsApplication::authManager()->authMethodEditWidget( it.value()->key(), this ) );
122  if ( !editWidget )
123  {
124  QgsDebugMsg( QStringLiteral( "Load auth method edit widget FAILED for auth method key (%1)" ).arg( it.value()->key() ) );
125  continue;
126  }
127  connect( editWidget, &QgsAuthMethodEdit::validityChanged, this, &QgsAuthConfigEdit::validateAuth );
128 
129  cmbAuthMethods->addItem( it.key(), QVariant( it.value()->key() ) );
130  stkwAuthMethods->addWidget( editWidget );
131  }
132 }
133 
134 void QgsAuthConfigEdit::loadConfig()
135 {
136  bool emptyAuthCfg = mAuthCfg.isEmpty();
137  authCfgEdit->setAllowEmptyId( emptyAuthCfg );
138  if ( emptyAuthCfg )
139  {
140  return;
141  }
142 
143  // edit mode requires master password to have been set and verified against auth db
144  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
145  {
146  mAuthCfg.clear();
147  return;
148  }
149 
150  QgsAuthMethodConfig mconfig;
151  if ( !QgsApplication::authManager()->loadAuthenticationConfig( mAuthCfg, mconfig, true ) )
152  {
153  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg: %1" ).arg( mAuthCfg ) );
154  return;
155  }
156 
157  if ( !mconfig.isValid( true ) )
158  {
159  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): invalid config" ).arg( mAuthCfg ) );
160  return;
161  }
162 
163  // load basic info
164  leName->setText( mconfig.name() );
165  leResource->setText( mconfig.uri() );
166  authCfgEdit->setAuthConfigId( mconfig.id() );
167 
168  QString authMethodKey = QgsApplication::authManager()->configAuthMethodKey( mAuthCfg );
169 
170  QgsDebugMsgLevel( QStringLiteral( "Loading authcfg: %1" ).arg( mAuthCfg ), 2 );
171  QgsDebugMsgLevel( QStringLiteral( "Loading auth method: %1" ).arg( authMethodKey ), 2 );
172 
173  if ( authMethodKey.isEmpty() )
174  {
175  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): no auth method found" ).arg( mAuthCfg ) );
176  return;
177  }
178 
179  if ( mconfig.method() != authMethodKey )
180  {
181  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): auth method and key mismatch" ).arg( mAuthCfg ) );
182  return;
183  }
184 
185  int indx = authMethodIndex( authMethodKey );
186  if ( indx == -1 )
187  {
188  QgsDebugMsg( QStringLiteral( "Loading FAILED for authcfg (%1): no edit widget loaded for auth method '%2'" )
189  .arg( mAuthCfg, authMethodKey ) );
190  if ( cmbAuthMethods->count() > 0 )
191  {
192  cmbAuthMethods->setCurrentIndex( 0 );
193  stkwAuthMethods->setCurrentIndex( 0 );
194  }
195  return;
196  }
197 
198  cmbAuthMethods->setCurrentIndex( indx );
199  stkwAuthMethods->setCurrentIndex( indx );
200 
201  QgsAuthMethodEdit *editWidget = currentEditWidget();
202  if ( !editWidget )
203  {
204  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED for authcfg (%1) and auth method key (%2)" )
205  .arg( mAuthCfg, authMethodKey ) );
206  return;
207  }
208 
209  editWidget->loadConfig( mconfig.configMap() );
210 }
211 
212 void QgsAuthConfigEdit::resetConfig()
213 {
214  clearAll();
215  loadConfig();
216  validateAuth();
217 }
218 
219 void QgsAuthConfigEdit::saveConfig()
220 {
221  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
222  return;
223 
224  QString authMethodKey = cmbAuthMethods->currentData().toString();
225 
226  QgsAuthMethodEdit *editWidget = currentEditWidget();
227  if ( !editWidget )
228  {
229  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED)" ) );
230  return;
231  }
232 
233  QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
234  if ( !authmethod )
235  {
236  QgsDebugMsg( QStringLiteral( "Save auth config FAILED when loading auth method instance from key (%1)" ).arg( authMethodKey ) );
237  return;
238  }
239 
240  QgsAuthMethodConfig mconfig;
241  mconfig.setName( leName->text() );
242  mconfig.setUri( leResource->text() );
243  mconfig.setMethod( authMethodKey );
244  mconfig.setVersion( authmethod->version() );
245  mconfig.setConfigMap( editWidget->configMap() );
246 
247  if ( !mconfig.isValid() )
248  {
249  QgsDebugMsg( QStringLiteral( "Save auth config FAILED: config invalid" ) );
250  return;
251  }
252 
253  QString authCfgId( authCfgEdit->configId() );
254  if ( !mAuthCfg.isEmpty() )
255  {
256  if ( authCfgId == mAuthCfg ) // update
257  {
258  mconfig.setId( mAuthCfg );
259  if ( QgsApplication::authManager()->updateAuthenticationConfig( mconfig ) )
260  {
261  emit authenticationConfigUpdated( mAuthCfg );
262  }
263  else
264  {
265  QgsDebugMsg( QStringLiteral( "Updating auth config FAILED for authcfg: %1" ).arg( mAuthCfg ) );
266  }
267  }
268  else // store new with unique ID, then delete previous
269  {
270  mconfig.setId( authCfgId );
271  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
272  {
273  emit authenticationConfigStored( authCfgId );
274  if ( !QgsApplication::authManager()->removeAuthenticationConfig( mAuthCfg ) )
275  {
276  QgsDebugMsg( QStringLiteral( "Removal of older auth config FAILED" ) );
277  }
278  mAuthCfg = authCfgId;
279  }
280  else
281  {
282  QgsDebugMsg( QStringLiteral( "Storing new auth config with user-created unique ID FAILED" ) );
283  }
284  }
285  }
286  else if ( mAuthCfg.isEmpty() )
287  {
288  if ( authCfgId.isEmpty() ) // create new with generated ID
289  {
290  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
291  {
292  mAuthCfg = mconfig.id();
293  emit authenticationConfigStored( mAuthCfg );
294  }
295  else
296  {
297  QgsDebugMsg( QStringLiteral( "Storing new auth config FAILED" ) );
298  }
299  }
300  else // create new with user-created unique ID
301  {
302  mconfig.setId( authCfgId );
303  if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
304  {
305  mAuthCfg = authCfgId;
306  emit authenticationConfigStored( mAuthCfg );
307  }
308  else
309  {
310  QgsDebugMsg( QStringLiteral( "Storing new auth config with user-created unique ID FAILED" ) );
311  }
312  }
313  }
314 
315  this->accept();
316 }
317 
318 void QgsAuthConfigEdit::btnClear_clicked()
319 {
320  QgsAuthMethodEdit *editWidget = currentEditWidget();
321  if ( !editWidget )
322  {
323  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED)" ) );
324  return;
325  }
326 
327  editWidget->clearConfig();
328 
329  validateAuth();
330 }
331 
332 void QgsAuthConfigEdit::clearAll()
333 {
334  leName->clear();
335  leResource->clear();
336  authCfgEdit->clear();
337 
338  for ( int i = 0; i < stkwAuthMethods->count(); i++ )
339  {
340  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->widget( i ) );
341  if ( editWidget )
342  {
343  editWidget->clearConfig();
344  }
345  }
346 
347  validateAuth();
348 }
349 
350 void QgsAuthConfigEdit::validateAuth()
351 {
352  bool authok = !leName->text().isEmpty();
353 
354  QgsAuthMethodEdit *editWidget = currentEditWidget();
355  if ( !editWidget )
356  {
357  QgsDebugMsg( QStringLiteral( "Cast to edit widget FAILED" ) );
358  }
359  else
360  {
361  authok = authok && editWidget->validateConfig();
362  }
363  authok = authok && authCfgEdit->validate();
364 
365  buttonBox->button( QDialogButtonBox::Save )->setEnabled( authok );
366 }
367 
368 void QgsAuthConfigEdit::leName_textChanged( const QString &txt )
369 {
370  Q_UNUSED( txt )
371  validateAuth();
372 }
373 
374 int QgsAuthConfigEdit::authMethodIndex( const QString &authMethodKey )
375 {
376  return cmbAuthMethods->findData( QVariant( authMethodKey ) );
377 }
378 
379 QgsAuthMethodEdit *QgsAuthConfigEdit::currentEditWidget()
380 {
381  return qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->currentWidget() );
382 }
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
void authenticationConfigStored(const QString &authcfg)
Emit generated id when a new config is saved to auth database.
void authenticationConfigUpdated(const QString &authcfg)
Emit current id when an existing config is updated in auth database.
QgsAuthConfigEdit(QWidget *parent=nullptr, const QString &authcfg=QString(), const QString &dataprovider=QString())
Create a dialog for editing an authentication configuration.
void validityChanged(bool valid)
Validity of the ID has changed.
bool isDisabled() const
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
QStringList configIds() const
Gets list of authentication ids from database.
QgsAuthMethod * authMethod(const QString &authMethodKey)
Gets authentication method from the config/provider cache via its key.
QStringList authMethodsKeys(const QString &dataprovider=QString())
Gets keys of supported authentication methods.
QString configAuthMethodKey(const QString &authcfg) const
Gets key of authentication method associated with config ID.
Configuration storage class for authentication method configurations.
Definition: qgsauthconfig.h:42
bool isValid(bool validateid=false) const
Whether the configuration is valid.
QString method() const
Textual key of the associated authentication method.
Definition: qgsauthconfig.h:76
const QString uri() const
A URI to auto-select a config when connecting to a resource.
Definition: qgsauthconfig.h:72
void setName(const QString &name)
Sets name of configuration.
Definition: qgsauthconfig.h:69
void setConfigMap(const QgsStringMap &map)
Set extended configuration map.
void setVersion(int version)
Sets version of the configuration.
Definition: qgsauthconfig.h:82
const QString name() const
Gets name of configuration.
Definition: qgsauthconfig.h:67
const QString id() const
Gets 'authcfg' 7-character alphanumeric ID of the config.
Definition: qgsauthconfig.h:62
QgsStringMap configMap() const
Gets extended configuration, mapped to key/value pairs of QStrings.
void setMethod(const QString &method)
Definition: qgsauthconfig.h:77
void setUri(const QString &uri)
Definition: qgsauthconfig.h:73
void setId(const QString &id)
Sets auth config ID.
Definition: qgsauthconfig.h:64
Abstract base class for the edit widget of authentication method plugins.
virtual bool validateConfig()=0
Validate the configuration of subclasses.
void validityChanged(bool valid)
Emitted when the configuration validatity changes.
virtual void clearConfig()=0
Clear GUI controls in subclassed widget.
virtual QgsStringMap configMap() const =0
The configuration key-vale map of subclasses.
virtual void loadConfig(const QgsStringMap &configmap)=0
Load an existing config map into subclassed widget.
Abstract base class for authentication method plugins.
Definition: qgsauthmethod.h:42
int version() const
Increment this if method is significantly updated, allow updater code to be written for previously st...
Definition: qgsauthmethod.h:77
virtual QString displayDescription() const =0
Translatable display version of the 'description()'.
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:156
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38