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