QGIS API Documentation  2.14.0-Essen
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 
27 
28 QgsAuthConfigEdit::QgsAuthConfigEdit( QWidget *parent , const QString& authcfg , const QString &dataprovider )
29  : QDialog( parent )
30  , mAuthCfg( authcfg )
31  , mDataProvider( dataprovider )
32  , mAuthNotifyLayout( nullptr )
33  , mAuthNotify( nullptr )
34 {
35  bool disabled = QgsAuthManager::instance()->isDisabled();
36  bool idok = true;
37 
38  if ( !disabled && !authcfg.isEmpty() )
39  {
40  idok = QgsAuthManager::instance()->configIds().contains( authcfg );
41  }
42 
43  if ( disabled || !idok )
44  {
45  mAuthNotifyLayout = new QVBoxLayout;
46  this->setLayout( mAuthNotifyLayout );
47 
48  QString msg( disabled ? QgsAuthManager::instance()->disabledMessage() : "" );
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( buttonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
63  connect( buttonBox, SIGNAL( accepted() ), this, SLOT( saveConfig() ) );
64  connect( buttonBox->button( QDialogButtonBox::Reset ), SIGNAL( clicked() ), this, SLOT( resetConfig() ) );
65 
66  populateAuthMethods();
67 
68  connect( cmbAuthMethods, SIGNAL( currentIndexChanged( int ) ),
69  stkwAuthMethods, SLOT( setCurrentIndex( int ) ) );
70  connect( cmbAuthMethods, SIGNAL( currentIndexChanged( int ) ),
71  this, SLOT( validateAuth() ) );
72 
73  connect( authCfgEdit, SIGNAL( validityChanged( bool ) ), this, SLOT( validateAuth() ) );
74 
75  // needed (if only combobox is ever changed)?
76  // connect( stkwAuthMethods, SIGNAL( currentChanged( int ) ),
77  // cmbAuthMethods, SLOT( setCurrentIndex( int ) ) );
78 
79  // connect( stkwAuthMethods, SIGNAL( currentChanged( int ) ),
80  // this, SLOT( validateAuth() ) );
81 
82  if ( cmbAuthMethods->count() > 0 )
83  {
84  cmbAuthMethods->setCurrentIndex( 0 );
85  stkwAuthMethods->setCurrentIndex( 0 );
86  }
87 
88  loadConfig();
89  validateAuth();
90 
91  leName->setFocus();
92  }
93 }
94 
96 {
97 }
98 
99 void QgsAuthConfigEdit::populateAuthMethods()
100 {
101  QStringList authMethodKeys = QgsAuthManager::instance()->authMethodsKeys( mDataProvider );
102 
103  // sort by auth method description attribute, then populate
105  Q_FOREACH ( const QString &authMethodKey, authMethodKeys )
106  {
107  QgsAuthMethod *authmethod = QgsAuthManager::instance()->authMethod( authMethodKey );
108  if ( !authmethod )
109  {
110  QgsDebugMsg( QString( "Load auth method instance FAILED for auth method key (%1)" ).arg( authMethodKey ) );
111  continue;
112  }
113  descmap.insert( authmethod->displayDescription(), authmethod );
114  }
115 
117  for ( it = descmap.begin(); it != descmap.end(); ++it )
118  {
119  QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit*>(
120  QgsAuthManager::instance()->authMethodEditWidget( it.value()->key(), this ) );
121  if ( !editWidget )
122  {
123  QgsDebugMsg( QString( "Load auth method edit widget FAILED for auth method key (%1)" ).arg( it.value()->key() ) );
124  continue;
125  }
126  connect( editWidget, SIGNAL( validityChanged( bool ) ), this, SLOT( 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 ( !QgsAuthManager::instance()->setMasterPassword( true ) )
144  {
145  mAuthCfg.clear();
146  return;
147  }
148 
149  QgsAuthMethodConfig mconfig;
150  if ( !QgsAuthManager::instance()->loadAuthenticationConfig( mAuthCfg, mconfig, true ) )
151  {
152  QgsDebugMsg( QString( "Loading FAILED for authcfg: %1" ).arg( mAuthCfg ) );
153  return;
154  }
155 
156  if ( !mconfig.isValid( true ) )
157  {
158  QgsDebugMsg( QString( "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 = QgsAuthManager::instance()->configAuthMethodKey( mAuthCfg );
168 
169  QgsDebugMsg( QString( "Loading authcfg: %1" ).arg( mAuthCfg ) );
170  QgsDebugMsg( QString( "Loading auth method: %1" ).arg( authMethodKey ) );
171 
172  if ( authMethodKey.isEmpty() )
173  {
174  QgsDebugMsg( QString( "Loading FAILED for authcfg (%1): no auth method found" ).arg( mAuthCfg ) );
175  return;
176  }
177 
178  if ( mconfig.method() != authMethodKey )
179  {
180  QgsDebugMsg( QString( "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( QString( "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( QString( "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 ( !QgsAuthManager::instance()->setMasterPassword( true ) )
221  return;
222 
223  QString authMethodKey = cmbAuthMethods->itemData( cmbAuthMethods->currentIndex() ).toString();
224 
225  QgsAuthMethodEdit *editWidget = currentEditWidget();
226  if ( !editWidget )
227  {
228  QgsDebugMsg( QString( "Cast to edit widget FAILED)" ) );
229  return;
230  }
231 
232  QgsAuthMethod *authmethod = QgsAuthManager::instance()->authMethod( authMethodKey );
233  if ( !authmethod )
234  {
235  QgsDebugMsg( QString( "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( "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 ( QgsAuthManager::instance()->updateAuthenticationConfig( mconfig ) )
259  {
260  emit authenticationConfigUpdated( mAuthCfg );
261  }
262  else
263  {
264  QgsDebugMsg( QString( "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 ( QgsAuthManager::instance()->storeAuthenticationConfig( mconfig ) )
271  {
272  emit authenticationConfigStored( authCfgId );
273  if ( !QgsAuthManager::instance()->removeAuthenticationConfig( mAuthCfg ) )
274  {
275  QgsDebugMsg( QString( "Removal of older auth config FAILED" ) );
276  }
277  mAuthCfg = authCfgId;
278  }
279  else
280  {
281  QgsDebugMsg( QString( "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( QString( "Storing new auth config FAILED" ) );
297  }
298  }
299  else // create new with user-created unique ID
300  {
301  mconfig.setId( authCfgId );
302  if ( QgsAuthManager::instance()->storeAuthenticationConfig( mconfig ) )
303  {
304  mAuthCfg = authCfgId;
305  emit authenticationConfigStored( mAuthCfg );
306  }
307  else
308  {
309  QgsDebugMsg( QString( "Storing new auth config with user-created unique ID FAILED" ) );
310  }
311  }
312  }
313 
314  this->accept();
315 }
316 
317 void QgsAuthConfigEdit::on_btnClear_clicked()
318 {
319  QgsAuthMethodEdit *editWidget = currentEditWidget();
320  if ( !editWidget )
321  {
322  QgsDebugMsg( QString( "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( QString( "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::on_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:68
bool close()
void setupUi(QWidget *widget)
void setId(const QString &id)
Set auth config ID.
Definition: qgsauthconfig.h:59
static QgsAuthManager * instance()
Enforce singleton pattern.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void rejected()
void authenticationConfigUpdated(const QString &authcfg)
Emit current id when an existing config is updated in auth database.
bool contains(const QString &str, Qt::CaseSensitivity cs) const
void accepted()
Abstract base class for the edit widget of authentication method plugins.
QStringList authMethodsKeys(const QString &dataprovider=QString())
Get keys of supported authentication methods.
QgsAuthMethod * authMethod(const QString &authMethodKey)
Get 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.
QString tr(const char *sourceText, const char *disambiguation, int n)
virtual void clearConfig()=0
Clear GUI controls in subclassed widget.
const QString name() const
Get name of configuration.
Definition: qgsauthconfig.h:62
void clear()
virtual void loadConfig(const QgsStringMap &configmap)=0
Load an existing config map into subclassed widget.
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
const QString uri() const
A URI to auto-select a config when connecting to a resource.
Definition: qgsauthconfig.h:67
void setLayout(QLayout *layout)
QgsStringMap configMap() const
Get extended configuration, mapped to key/value pairs of QStrings.
Definition: qgsauthconfig.h:97
void setMethod(const QString &method)
Definition: qgsauthconfig.h:72
Configuration storage class for authentication method configurations.
Definition: qgsauthconfig.h:36
bool isEmpty() const
int version() const
Increment this if method is significantly updated, allow updater code to be written for previously st...
Definition: qgsauthmethod.h:69
const QString id() const
Get &#39;authcfg&#39; 7-character alphanumeric ID of the config.
Definition: qgsauthconfig.h:57
iterator end()
QWidget * authMethodEditWidget(const QString &authMethodKey, QWidget *parent)
Get authentication method edit widget via its key.
T & value() const
virtual void accept()
iterator begin()
QString configAuthMethodKey(const QString &authcfg) const
Get 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:33
QStringList configIds() const
Get list of authentication ids from database.
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)
Set version of the configuration.
Definition: qgsauthconfig.h:77
const Key & key() const
iterator insert(const Key &key, const T &value)
bool isValid(bool validateid=false) const
Whether the configuration is valid.
bool isDisabled() const
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setName(const QString &name)
Set name of configuration.
Definition: qgsauthconfig.h:64
void setConfigMap(const QgsStringMap &map)
Set extended configuration map.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString method() const
Textual key of the associated authentication method.
Definition: qgsauthconfig.h:71