QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgsauthconfigselect.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsauthconfigselect.cpp
3  ---------------------
4  begin : October 5, 2014
5  copyright : (C) 2014 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 "qgsauthconfigselect.h"
18 #include "ui_qgsauthconfigselect.h"
19 
20 #include <QHash>
21 #include <QMessageBox>
22 #include <QTimer>
23 
24 #include "qgsauthconfig.h"
25 #include "qgsauthguiutils.h"
26 #include "qgsauthmanager.h"
27 #include "qgsauthconfigedit.h"
28 #include "qgslogger.h"
29 #include "qgsapplication.h"
30 
31 
32 QgsAuthConfigSelect::QgsAuthConfigSelect( QWidget *parent, const QString &dataprovider )
33  : QWidget( parent )
34  , mDataProvider( dataprovider )
35 {
36  if ( QgsApplication::authManager()->isDisabled() )
37  {
38  mDisabled = true;
39  mAuthNotifyLayout = new QVBoxLayout;
40  this->setLayout( mAuthNotifyLayout );
41  mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
42  mAuthNotifyLayout->addWidget( mAuthNotify );
43  }
44  else
45  {
46  setupUi( this );
47  connect( cmbConfigSelect, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAuthConfigSelect::cmbConfigSelect_currentIndexChanged );
48  connect( btnConfigAdd, &QToolButton::clicked, this, &QgsAuthConfigSelect::btnConfigAdd_clicked );
49  connect( btnConfigEdit, &QToolButton::clicked, this, &QgsAuthConfigSelect::btnConfigEdit_clicked );
50  connect( btnConfigRemove, &QToolButton::clicked, this, &QgsAuthConfigSelect::btnConfigRemove_clicked );
51  connect( btnConfigMsgClear, &QToolButton::clicked, this, &QgsAuthConfigSelect::btnConfigMsgClear_clicked );
52 
53  // Set icons and remove texts
54  btnConfigAdd->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyAdd.svg" ) ) );
55  btnConfigRemove->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/symbologyRemove.svg" ) ) );
56  btnConfigEdit->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) ) );
57  btnConfigMsgClear->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconClose.svg" ) ) );
58 
59  btnConfigAdd->setText( QString() );
60  btnConfigRemove->setText( QString() );
61  btnConfigEdit->setText( QString() );
62  btnConfigMsgClear->setText( QString() );
63 
64  leConfigMsg->setStyleSheet( QStringLiteral( "QLineEdit{background-color: %1}" )
65  .arg( QgsAuthGuiUtils::yellowColor().name() ) );
66 
67  clearConfig();
68  clearMessage();
69  populateConfigSelector();
70  }
71 }
72 
73 void QgsAuthConfigSelect::setConfigId( const QString &authcfg )
74 {
75  if ( mDisabled && mAuthNotify )
76  {
77  mAuthNotify->setText( QgsApplication::authManager()->disabledMessage() + "\n\n" +
78  tr( "Authentication config id not loaded: %1" ).arg( authcfg ) );
79  }
80  else
81  {
82  if ( mAuthCfg != authcfg )
83  {
84  mAuthCfg = authcfg;
85  }
86  // avoid duplicate call to loadConfig(), which may potentially be triggered by combo box index changes in the
87  // call to populateConfigSelector(). We *always* call loadConfig() after this, so we don't want to do it twice.
88  mTemporarilyBlockLoad = true;
89  populateConfigSelector();
90  mTemporarilyBlockLoad = false;
91  loadConfig();
92  }
93 }
94 
95 void QgsAuthConfigSelect::setDataProviderKey( const QString &key )
96 {
97  if ( mDisabled )
98  {
99  return;
100  }
101 
102  mDataProvider = key;
103  populateConfigSelector();
104 }
105 
106 void QgsAuthConfigSelect::loadConfig()
107 {
108  clearConfig();
109  if ( !mAuthCfg.isEmpty() && mConfigs.contains( mAuthCfg ) )
110  {
111  QgsAuthMethodConfig config = mConfigs.value( mAuthCfg );
112  QgsAuthMethod *authmethod = QgsApplication::authManager()->configAuthMethod( mAuthCfg );
113  QString methoddesc = tr( "Missing authentication method description" );
114  if ( authmethod )
115  {
116  methoddesc = authmethod->description();
117  }
118  cmbConfigSelect->setToolTip( tr( "<ul><li><b>Method type:</b> %1</li>"
119  "<li><b>Configuration ID:</b> %2</li></ul>" ).arg( methoddesc, config.id( ) ) );
120  btnConfigEdit->setEnabled( true );
121  btnConfigRemove->setEnabled( true );
122  }
123  emit selectedConfigIdChanged( mAuthCfg );
124 }
125 
126 void QgsAuthConfigSelect::clearConfig()
127 {
128  cmbConfigSelect->setToolTip( QString() );
129  btnConfigEdit->setEnabled( false );
130  btnConfigRemove->setEnabled( false );
131 }
132 
133 void QgsAuthConfigSelect::validateConfig()
134 {
135  if ( !mAuthCfg.isEmpty() && !mConfigs.contains( mAuthCfg ) )
136  {
137  showMessage( tr( "Configuration '%1' not in database" ).arg( mAuthCfg ) );
138  mAuthCfg.clear();
139  }
140 }
141 
142 void QgsAuthConfigSelect::populateConfigSelector()
143 {
144  loadAvailableConfigs();
145  validateConfig();
146 
147  cmbConfigSelect->blockSignals( true );
148  cmbConfigSelect->clear();
149  cmbConfigSelect->addItem( tr( "No Authentication" ), "0" );
150 
151  QgsStringMap sortmap;
152  QgsAuthMethodConfigsMap::const_iterator cit = mConfigs.constBegin();
153  for ( cit = mConfigs.constBegin(); cit != mConfigs.constEnd(); ++cit )
154  {
155  QgsAuthMethodConfig config = cit.value();
156  sortmap.insert( QStringLiteral( "%1 (%2)" ).arg( config.name(), config.method() ), cit.key() );
157  }
158 
159  QgsStringMap::const_iterator sm = sortmap.constBegin();
160  for ( sm = sortmap.constBegin(); sm != sortmap.constEnd(); ++sm )
161  {
162  cmbConfigSelect->addItem( sm.key(), sm.value() );
163  }
164  cmbConfigSelect->blockSignals( false );
165 
166  int indx = 0;
167  if ( !mAuthCfg.isEmpty() )
168  {
169  indx = cmbConfigSelect->findData( mAuthCfg );
170  }
171  cmbConfigSelect->setCurrentIndex( indx > 0 ? indx : 0 );
172 }
173 
174 void QgsAuthConfigSelect::showMessage( const QString &msg )
175 {
176  if ( mDisabled )
177  {
178  return;
179  }
180  leConfigMsg->setText( msg );
181  frConfigMsg->setVisible( true );
182 }
183 
185 {
186  if ( mDisabled )
187  {
188  return;
189  }
190  leConfigMsg->clear();
191  frConfigMsg->setVisible( false );
192 }
193 
194 void QgsAuthConfigSelect::loadAvailableConfigs()
195 {
196  mConfigs.clear();
197  mConfigs = QgsApplication::authManager()->availableAuthMethodConfigs( mDataProvider );
198 }
199 
200 void QgsAuthConfigSelect::cmbConfigSelect_currentIndexChanged( int index )
201 {
202  QString authcfg = cmbConfigSelect->itemData( index ).toString();
203  mAuthCfg = ( !authcfg.isEmpty() && authcfg != QLatin1String( "0" ) ) ? authcfg : QString();
204  if ( !mTemporarilyBlockLoad )
205  loadConfig();
206 }
207 
208 void QgsAuthConfigSelect::btnConfigAdd_clicked()
209 {
210  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
211  return;
212 
213  QgsAuthConfigEdit *ace = new QgsAuthConfigEdit( this, QString(), mDataProvider );
214  ace->setWindowModality( Qt::WindowModal );
215  if ( ace->exec() )
216  {
217  setConfigId( ace->configId() );
218  }
219  ace->deleteLater();
220 }
221 
222 void QgsAuthConfigSelect::btnConfigEdit_clicked()
223 {
224  if ( !QgsApplication::authManager()->setMasterPassword( true ) )
225  return;
226 
227  QgsAuthConfigEdit *ace = new QgsAuthConfigEdit( this, mAuthCfg, mDataProvider );
228  ace->setWindowModality( Qt::WindowModal );
229  if ( ace->exec() )
230  {
231  //qDebug( "Edit returned config Id: %s", ace->configId().toLatin1().constData() );
232  setConfigId( ace->configId() );
233  }
234  ace->deleteLater();
235 }
236 
237 void QgsAuthConfigSelect::btnConfigRemove_clicked()
238 {
239  if ( QMessageBox::warning( this, tr( "Remove Authentication" ),
240  tr( "Are you sure that you want to permanently remove this configuration right now?\n\n"
241  "Operation can NOT be undone!" ),
242  QMessageBox::Ok | QMessageBox::Cancel,
243  QMessageBox::Cancel ) == QMessageBox::Cancel )
244  {
245  return;
246  }
247 
248  if ( QgsApplication::authManager()->removeAuthenticationConfig( mAuthCfg ) )
249  {
250  emit selectedConfigIdRemoved( mAuthCfg );
251  setConfigId( QString() );
252  }
253 }
254 
255 void QgsAuthConfigSelect::btnConfigMsgClear_clicked()
256 {
257  clearMessage();
258 }
259 
260 
262 
263 #include <QPushButton>
264 
265 QgsAuthConfigUriEdit::QgsAuthConfigUriEdit( QWidget *parent, const QString &datauri, const QString &dataprovider )
266  : QDialog( parent )
267 {
268  if ( QgsApplication::authManager()->isDisabled() )
269  {
270  mDisabled = true;
271  mAuthNotifyLayout = new QVBoxLayout;
272  this->setLayout( mAuthNotifyLayout );
273  mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
274  mAuthNotifyLayout->addWidget( mAuthNotify );
275  }
276  else
277  {
278  setupUi( this );
279 
280  setWindowTitle( tr( "Authentication Config ID String Editor" ) );
281 
282  buttonBox->button( QDialogButtonBox::Close )->setDefault( true );
283  connect( buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close );
284  connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsAuthConfigUriEdit::saveChanges );
285 
286  connect( buttonBox->button( QDialogButtonBox::Reset ), &QAbstractButton::clicked, this, &QgsAuthConfigUriEdit::resetChanges );
287 
288  connect( wdgtAuthSelect, &QgsAuthConfigSelect::selectedConfigIdChanged, this, &QgsAuthConfigUriEdit::authCfgUpdated );
289  connect( wdgtAuthSelect, &QgsAuthConfigSelect::selectedConfigIdRemoved, this, &QgsAuthConfigUriEdit::authCfgRemoved );
290 
291  wdgtAuthSelect->setDataProviderKey( dataprovider );
292  setDataSourceUri( datauri );
293  }
294 }
295 
296 void QgsAuthConfigUriEdit::setDataSourceUri( const QString &datauri )
297 {
298  if ( mDisabled )
299  {
300  return;
301  }
302  if ( datauri.isEmpty() )
303  return;
304 
305  mDataUri = mDataUriOrig = datauri;
306 
307  teDataUri->setPlainText( mDataUri );
308 
309  if ( authCfgIndex() == -1 )
310  {
311  wdgtAuthSelect->showMessage( tr( "No authcfg in Data Source URI" ) );
312  return;
313  }
314 
315  selectAuthCfgInUri();
316 
317  mAuthCfg = authCfgFromUri();
318 
319  QgsDebugMsg( QStringLiteral( "Parsed authcfg ID: %1" ).arg( mAuthCfg ) );
320 
321  wdgtAuthSelect->blockSignals( true );
322  wdgtAuthSelect->setConfigId( mAuthCfg );
323  wdgtAuthSelect->blockSignals( false );
324 }
325 
327 {
328  if ( mDisabled )
329  {
330  return QString();
331  }
332  return mDataUri;
333 }
334 
335 bool QgsAuthConfigUriEdit::hasConfigId( const QString &txt )
336 {
337  if ( QgsApplication::authManager()->isDisabled() )
338  {
339  return false;
340  }
341  return QgsApplication::authManager()->hasConfigId( txt );
342 }
343 
344 void QgsAuthConfigUriEdit::saveChanges()
345 {
346  this->accept();
347 }
348 
349 void QgsAuthConfigUriEdit::resetChanges()
350 {
351  wdgtAuthSelect->clearMessage();
352  setDataSourceUri( mDataUriOrig );
353 }
354 
355 void QgsAuthConfigUriEdit::authCfgUpdated( const QString &authcfg )
356 {
357  mAuthCfg = authcfg;
358 
359  if ( mAuthCfg.size() != 7 )
360  {
361  mAuthCfg.clear();
362  removeAuthCfgFromUri();
363  }
364  else
365  {
366  updateUriWithAuthCfg();
367  }
368  teDataUri->clear();
369  teDataUri->setPlainText( mDataUri );
370  selectAuthCfgInUri();
371 }
372 
373 void QgsAuthConfigUriEdit::authCfgRemoved( const QString &authcfg )
374 {
375  if ( authCfgFromUri() == authcfg )
376  {
377  removeAuthCfgFromUri();
378  }
379 }
380 
381 int QgsAuthConfigUriEdit::authCfgIndex()
382 {
383  QRegExp rx( QgsApplication::authManager()->configIdRegex() );
384  return rx.indexIn( mDataUri );
385 }
386 
387 QString QgsAuthConfigUriEdit::authCfgFromUri()
388 {
389  int startindex = authCfgIndex();
390  if ( startindex == -1 )
391  return QString();
392 
393  return mDataUri.mid( startindex + 8, 7 );
394 }
395 
396 void QgsAuthConfigUriEdit::selectAuthCfgInUri()
397 {
398  int startindex = authCfgIndex();
399  if ( startindex == -1 )
400  return;
401 
402  // authcfg=.{7} will always be 15 chars
403  QTextCursor tc = teDataUri->textCursor();
404  tc.setPosition( startindex );
405  tc.setPosition( startindex + 15, QTextCursor::KeepAnchor );
406  teDataUri->setTextCursor( tc );
407  teDataUri->setFocus();
408 }
409 
410 void QgsAuthConfigUriEdit::updateUriWithAuthCfg()
411 {
412  int startindex = authCfgIndex();
413  if ( startindex == -1 )
414  {
415  if ( mAuthCfg.size() == 7 )
416  {
417  wdgtAuthSelect->showMessage( tr( "Adding authcfg to URI not supported" ) );
418  }
419  return;
420  }
421 
422  mDataUri = mDataUri.replace( startindex + 8, 7, mAuthCfg );
423 }
424 
425 void QgsAuthConfigUriEdit::removeAuthCfgFromUri()
426 {
427  int startindex = authCfgIndex();
428  if ( startindex == -1 )
429  return;
430 
431  // add any preceding space so two spaces will not result after removal
432  int rmvlen = 15;
433  if ( startindex - 1 >= 0
434  && ( mDataUri.at( startindex - 1 ).isSpace()
435  || mDataUri.at( startindex - 1 ) == QChar( '&' ) ) )
436  {
437  startindex -= 1;
438  rmvlen += 1;
439  }
440 
441  // trim any leftover spaces or & from ends
442  mDataUri = mDataUri.remove( startindex, rmvlen ).trimmed();
443  if ( mDataUri.at( 0 ) == QChar( '&' ) )
444  mDataUri = mDataUri.remove( 0, 1 );
445 
446  // trim any & from
447 
448  mAuthCfg.clear();
449 }
450 
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Widget for editing an authentication configuration.
const QString configId() const
Authentication config id, updated with generated id when a new config is saved to auth database.
void clearMessage()
Clear and hide small message bar.
void setConfigId(const QString &authcfg)
Sets the authentication config id for the resource.
void selectedConfigIdRemoved(const QString &authcfg)
Emitted when authentication config is removed.
QgsAuthConfigSelect(QWidget *parent=nullptr, const QString &dataprovider=QString())
Create a dialog for setting an associated authentication config, either from existing configs,...
void selectedConfigIdChanged(const QString &authcfg)
Emitted when authentication config is changed or missing.
void setDataProviderKey(const QString &key)
Sets key of layer provider, if applicable.
void showMessage(const QString &msg)
Show a small message bar with a close button.
void setDataSourceUri(const QString &datauri)
Sets the data source URI to parse.
static bool hasConfigId(const QString &txt)
Whether a string contains an authcfg ID.
QString dataSourceUri()
The returned, possibly edited data source URI.
QgsAuthConfigUriEdit(QWidget *parent=nullptr, const QString &datauri=QString(), const QString &dataprovider=QString())
Construct wrapper dialog for select widget to edit an authcfg in a data source URI.
static QColor yellowColor()
Yellow color representing caution regarding action.
QgsAuthMethod * configAuthMethod(const QString &authcfg)
Gets authentication method from the config/provider cache.
bool hasConfigId(const QString &txt) const
Returns whether a string includes an authcfg ID token.
QgsAuthMethodConfigsMap availableAuthMethodConfigs(const QString &dataprovider=QString())
Gets mapping of authentication config ids and their base configs (not decrypted data)
Configuration storage class for authentication method configurations.
Definition: qgsauthconfig.h:39
QString method() const
Textual key of the associated authentication method.
Definition: qgsauthconfig.h:73
const QString name() const
Gets name of configuration.
Definition: qgsauthconfig.h:64
const QString id() const
Gets 'authcfg' 7-character alphanumeric ID of the config.
Definition: qgsauthconfig.h:59
Abstract base class for authentication method plugins.
Definition: qgsauthmethod.h:37
virtual QString description() const =0
A non-translated short description representing the auth method for use in debug output and About dia...
QMap< QString, QString > QgsStringMap
Definition: qgis.h:759
#define QgsDebugMsg(str)
Definition: qgslogger.h:38