QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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"
27
28#include <QHash>
29#include <QMessageBox>
30#include <QTimer>
31#include <QRegularExpression>
32
33
34QgsAuthConfigSelect::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();
71 populateConfigSelector();
72 }
73}
74
75void 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
98{
99 if ( mDisabled )
100 {
101 return;
102 }
103
104 mDataProvider = key;
105 populateConfigSelector();
106}
107
108void 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" );
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
129void QgsAuthConfigSelect::clearConfig()
130{
131 cmbConfigSelect->setToolTip( QString() );
132 btnConfigEdit->setEnabled( false );
133 btnConfigRemove->setEnabled( false );
134}
135
136void 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
145void 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
177void 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
197void QgsAuthConfigSelect::loadAvailableConfigs()
198{
199 mConfigs.clear();
200 mConfigs = QgsApplication::authManager()->availableAuthMethodConfigs( mDataProvider );
201}
202
203void 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
211void 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
225void 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
240void 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
258void QgsAuthConfigSelect::btnConfigMsgClear_clicked()
259{
260 clearMessage();
261}
262
263
265
266#include <QPushButton>
267
268QgsAuthConfigUriEdit::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
299void 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 QgsDebugMsgLevel( QStringLiteral( "Parsed authcfg ID: %1" ).arg( mAuthCfg ), 2 );
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
338bool QgsAuthConfigUriEdit::hasConfigId( const QString &txt )
339{
340 if ( QgsApplication::authManager()->isDisabled() )
341 {
342 return false;
343 }
345}
346
347void QgsAuthConfigUriEdit::saveChanges()
348{
349 this->accept();
350}
351
352void QgsAuthConfigUriEdit::resetChanges()
353{
354 wdgtAuthSelect->clearMessage();
355 setDataSourceUri( mDataUriOrig );
356}
357
358void 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
376void QgsAuthConfigUriEdit::authCfgRemoved( const QString &authcfg )
377{
378 if ( authCfgFromUri() == authcfg )
379 {
380 removeAuthCfgFromUri();
381 }
382}
383
384int QgsAuthConfigUriEdit::authCfgIndex()
385{
386 return mDataUri.indexOf( QRegularExpression( QgsApplication::authManager()->configIdRegex() ) );
387}
388
389QString 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
398void 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
412void 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
427void 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.
static bool hasConfigId(const QString &txt)
Returns whether a string includes an authcfg ID token.
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.
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:5737
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39