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