QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
22#include "qgsauthconfig.h"
23#include "qgsauthconfigidedit.h"
24#include "qgsauthmanager.h"
25#include "qgsauthmethodedit.h"
26#include "qgslogger.h"
27#include "qgsapplication.h"
28#include "qgsgui.h"
29
30QgsAuthConfigEdit::QgsAuthConfigEdit( QWidget *parent, const QString &authcfg, const QString &dataprovider )
31 : QDialog( parent )
32 , mAuthCfg( authcfg )
33 , mDataProvider( dataprovider )
34
35{
36 const bool disabled = QgsApplication::authManager()->isDisabled();
37 bool idok = true;
38
39 if ( !disabled && !authcfg.isEmpty() )
40 {
41 idok = QgsApplication::authManager()->configIds().contains( authcfg );
42 }
43
44 if ( disabled || !idok )
45 {
46 mAuthNotifyLayout = new QVBoxLayout;
47 this->setLayout( mAuthNotifyLayout );
48
49 QString msg( disabled ? QgsApplication::authManager()->disabledMessage() : QString() );
50 if ( !authcfg.isEmpty() )
51 {
52 msg += "\n\n" + tr( "Authentication config id not loaded: %1" ).arg( authcfg );
53 }
54 mAuthNotify = new QLabel( msg, this );
55 mAuthNotifyLayout->addWidget( mAuthNotify );
56
57 mAuthCfg.clear(); // otherwise will continue to try authenticate (and fail) after save
58 buttonBox->button( QDialogButtonBox::Save )->setEnabled( false );
59 }
60 else
61 {
62 setupUi( this );
63 connect( btnClear, &QToolButton::clicked, this, &QgsAuthConfigEdit::btnClear_clicked );
64 connect( leName, &QLineEdit::textChanged, this, &QgsAuthConfigEdit::leName_textChanged );
65 connect( buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close );
66 connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsAuthConfigEdit::saveConfig );
67 connect( buttonBox->button( QDialogButtonBox::Reset ), &QAbstractButton::clicked, this, &QgsAuthConfigEdit::resetConfig );
68
69 populateAuthMethods();
70
71 connect( cmbAuthMethods, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
72 stkwAuthMethods, &QStackedWidget::setCurrentIndex );
73 connect( cmbAuthMethods, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
74 this, [ = ] { validateAuth(); } );
75
76 connect( authCfgEdit, &QgsAuthConfigIdEdit::validityChanged, this, &QgsAuthConfigEdit::validateAuth );
77
78 // needed (if only combobox is ever changed)?
79 // connect( stkwAuthMethods, SIGNAL( currentChanged( int ) ),
80 // cmbAuthMethods, SLOT( setCurrentIndex( int ) ) );
81
82 // connect( stkwAuthMethods, SIGNAL( currentChanged( int ) ),
83 // this, SLOT( validateAuth() ) );
84
85 if ( cmbAuthMethods->count() > 0 )
86 {
87 cmbAuthMethods->setCurrentIndex( 0 );
88 stkwAuthMethods->setCurrentIndex( 0 );
89 }
90
91 loadConfig();
92 validateAuth();
93
94 leName->setFocus();
95 }
96
98}
99
100void QgsAuthConfigEdit::populateAuthMethods()
101{
102 const QStringList authMethodKeys = QgsApplication::authManager()->authMethodsKeys( mDataProvider );
103
104 // sort by auth method description attribute, then populate
105 QMap<QString, const QgsAuthMethodMetadata *> descmap;
106 const auto constAuthMethodKeys = authMethodKeys;
107 for ( const QString &authMethodKey : constAuthMethodKeys )
108 {
110 if ( !meta )
111 {
112 QgsDebugError( QStringLiteral( "Load auth method instance FAILED for auth method key (%1)" ).arg( authMethodKey ) );
113 continue;
114 }
115 descmap.insert( meta->description(), meta );
116 }
117
118 QMap<QString, const QgsAuthMethodMetadata *>::iterator it = descmap.begin();
119 for ( it = descmap.begin(); it != descmap.end(); ++it )
120 {
121 QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>(
122 QgsApplication::authManager()->authMethodEditWidget( it.value()->key(), this ) );
123 if ( !editWidget )
124 {
125 QgsDebugError( QStringLiteral( "Load auth method edit widget FAILED for auth method key (%1)" ).arg( it.value()->key() ) );
126 continue;
127 }
128 connect( editWidget, &QgsAuthMethodEdit::validityChanged, this, &QgsAuthConfigEdit::validateAuth );
129
130 cmbAuthMethods->addItem( it.key(), QVariant( it.value()->key() ) );
131 stkwAuthMethods->addWidget( editWidget );
132 }
133}
134
135void QgsAuthConfigEdit::loadConfig()
136{
137 const bool emptyAuthCfg = mAuthCfg.isEmpty();
138 authCfgEdit->setAllowEmptyId( emptyAuthCfg );
139 if ( emptyAuthCfg )
140 {
141 return;
142 }
143
144 // edit mode requires master password to have been set and verified against auth db
145 if ( !QgsApplication::authManager()->setMasterPassword( true ) )
146 {
147 mAuthCfg.clear();
148 return;
149 }
150
151 QgsAuthMethodConfig mconfig;
152 if ( !QgsApplication::authManager()->loadAuthenticationConfig( mAuthCfg, mconfig, true ) )
153 {
154 QgsDebugError( QStringLiteral( "Loading FAILED for authcfg: %1" ).arg( mAuthCfg ) );
155 return;
156 }
157
158 if ( !mconfig.isValid( true ) )
159 {
160 QgsDebugError( QStringLiteral( "Loading FAILED for authcfg (%1): invalid config" ).arg( mAuthCfg ) );
161 return;
162 }
163
164 // load basic info
165 leName->setText( mconfig.name() );
166 leResource->setText( mconfig.uri() );
167 authCfgEdit->setAuthConfigId( mconfig.id() );
168
169 const QString authMethodKey = QgsApplication::authManager()->configAuthMethodKey( mAuthCfg );
170
171 QgsDebugMsgLevel( QStringLiteral( "Loading authcfg: %1" ).arg( mAuthCfg ), 2 );
172 QgsDebugMsgLevel( QStringLiteral( "Loading auth method: %1" ).arg( authMethodKey ), 2 );
173
174 if ( authMethodKey.isEmpty() )
175 {
176 QgsDebugError( QStringLiteral( "Loading FAILED for authcfg (%1): no auth method found" ).arg( mAuthCfg ) );
177 return;
178 }
179
180 if ( mconfig.method() != authMethodKey )
181 {
182 QgsDebugError( QStringLiteral( "Loading FAILED for authcfg (%1): auth method and key mismatch" ).arg( mAuthCfg ) );
183 return;
184 }
185
186 const int indx = authMethodIndex( authMethodKey );
187 if ( indx == -1 )
188 {
189 QgsDebugError( QStringLiteral( "Loading FAILED for authcfg (%1): no edit widget loaded for auth method '%2'" )
190 .arg( mAuthCfg, authMethodKey ) );
191 if ( cmbAuthMethods->count() > 0 )
192 {
193 cmbAuthMethods->setCurrentIndex( 0 );
194 stkwAuthMethods->setCurrentIndex( 0 );
195 }
196 return;
197 }
198
199 cmbAuthMethods->setCurrentIndex( indx );
200 stkwAuthMethods->setCurrentIndex( indx );
201
202 QgsAuthMethodEdit *editWidget = currentEditWidget();
203 if ( !editWidget )
204 {
205 QgsDebugError( QStringLiteral( "Cast to edit widget FAILED for authcfg (%1) and auth method key (%2)" )
206 .arg( mAuthCfg, authMethodKey ) );
207 return;
208 }
209
210 editWidget->loadConfig( mconfig.configMap() );
211}
212
213void QgsAuthConfigEdit::resetConfig()
214{
215 clearAll();
216 loadConfig();
217 validateAuth();
218}
219
220void QgsAuthConfigEdit::saveConfig()
221{
222 if ( !QgsApplication::authManager()->setMasterPassword( true ) )
223 return;
224
225 const QString authMethodKey = cmbAuthMethods->currentData().toString();
226
227 QgsAuthMethodEdit *editWidget = currentEditWidget();
228 if ( !editWidget )
229 {
230 QgsDebugError( QStringLiteral( "Cast to edit widget FAILED)" ) );
231 return;
232 }
233
234 QgsAuthMethod *authmethod = QgsApplication::authManager()->authMethod( authMethodKey );
235 if ( !authmethod )
236 {
237 QgsDebugError( QStringLiteral( "Save auth config FAILED when loading auth method instance from key (%1)" ).arg( authMethodKey ) );
238 return;
239 }
240
241 QgsAuthMethodConfig mconfig;
242 mconfig.setName( leName->text() );
243 mconfig.setUri( leResource->text() );
244 mconfig.setMethod( authMethodKey );
245 mconfig.setVersion( authmethod->version() );
246 mconfig.setConfigMap( editWidget->configMap() );
247
248 if ( !mconfig.isValid() )
249 {
250 QgsDebugError( QStringLiteral( "Save auth config FAILED: config invalid" ) );
251 return;
252 }
253
254 const QString authCfgId( authCfgEdit->configId() );
255 if ( !mAuthCfg.isEmpty() )
256 {
257 if ( authCfgId == mAuthCfg ) // update
258 {
259 mconfig.setId( mAuthCfg );
260 if ( QgsApplication::authManager()->updateAuthenticationConfig( mconfig ) )
261 {
262 emit authenticationConfigUpdated( mAuthCfg );
263 }
264 else
265 {
266 QgsDebugError( QStringLiteral( "Updating auth config FAILED for authcfg: %1" ).arg( mAuthCfg ) );
267 }
268 }
269 else // store new with unique ID, then delete previous
270 {
271 mconfig.setId( authCfgId );
272 if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
273 {
274 emit authenticationConfigStored( authCfgId );
275 if ( !QgsApplication::authManager()->removeAuthenticationConfig( mAuthCfg ) )
276 {
277 QgsDebugError( QStringLiteral( "Removal of older auth config FAILED" ) );
278 }
279 mAuthCfg = authCfgId;
280 }
281 else
282 {
283 QgsDebugError( QStringLiteral( "Storing new auth config with user-created unique ID FAILED" ) );
284 }
285 }
286 }
287 else if ( mAuthCfg.isEmpty() )
288 {
289 if ( authCfgId.isEmpty() ) // create new with generated ID
290 {
291 if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
292 {
293 mAuthCfg = mconfig.id();
294 emit authenticationConfigStored( mAuthCfg );
295 }
296 else
297 {
298 QgsDebugError( QStringLiteral( "Storing new auth config FAILED" ) );
299 }
300 }
301 else // create new with user-created unique ID
302 {
303 mconfig.setId( authCfgId );
304 if ( QgsApplication::authManager()->storeAuthenticationConfig( mconfig ) )
305 {
306 mAuthCfg = authCfgId;
307 emit authenticationConfigStored( mAuthCfg );
308 }
309 else
310 {
311 QgsDebugError( QStringLiteral( "Storing new auth config with user-created unique ID FAILED" ) );
312 }
313 }
314 }
315
316 this->accept();
317}
318
319void QgsAuthConfigEdit::btnClear_clicked()
320{
321 QgsAuthMethodEdit *editWidget = currentEditWidget();
322 if ( !editWidget )
323 {
324 QgsDebugError( QStringLiteral( "Cast to edit widget FAILED)" ) );
325 return;
326 }
327
328 editWidget->clearConfig();
329
330 validateAuth();
331}
332
333void QgsAuthConfigEdit::clearAll()
334{
335 leName->clear();
336 leResource->clear();
337 authCfgEdit->clear();
338
339 for ( int i = 0; i < stkwAuthMethods->count(); i++ )
340 {
341 QgsAuthMethodEdit *editWidget = qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->widget( i ) );
342 if ( editWidget )
343 {
344 editWidget->clearConfig();
345 }
346 }
347
348 validateAuth();
349}
350
351void QgsAuthConfigEdit::validateAuth()
352{
353 bool authok = !leName->text().isEmpty();
354
355 QgsAuthMethodEdit *editWidget = currentEditWidget();
356 if ( !editWidget )
357 {
358 QgsDebugError( QStringLiteral( "Cast to edit widget FAILED" ) );
359 }
360 else
361 {
362 authok = authok && editWidget->validateConfig();
363 }
364 authok = authok && authCfgEdit->validate();
365
366 buttonBox->button( QDialogButtonBox::Save )->setEnabled( authok );
367}
368
369void QgsAuthConfigEdit::leName_textChanged( const QString &txt )
370{
371 Q_UNUSED( txt )
372 validateAuth();
373}
374
375int QgsAuthConfigEdit::authMethodIndex( const QString &authMethodKey )
376{
377 return cmbAuthMethods->findData( QVariant( authMethodKey ) );
378}
379
380QgsAuthMethodEdit *QgsAuthConfigEdit::currentEditWidget()
381{
382 return qobject_cast<QgsAuthMethodEdit *>( stkwAuthMethods->currentWidget() );
383}
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
void authenticationConfigStored(const QString &authcfg)
Emit generated id when a new config is saved to auth database.
void authenticationConfigUpdated(const QString &authcfg)
Emit current id when an existing config is updated in auth database.
QgsAuthConfigEdit(QWidget *parent=nullptr, const QString &authcfg=QString(), const QString &dataprovider=QString())
Create a dialog for editing an authentication configuration.
void validityChanged(bool valid)
Validity of the ID has changed.
bool isDisabled() const
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
QStringList configIds() const
Gets list of authentication ids from database.
QgsAuthMethod * authMethod(const QString &authMethodKey)
Gets authentication method from the config/provider cache via its key.
QStringList authMethodsKeys(const QString &dataprovider=QString())
Gets keys of supported authentication methods.
const QgsAuthMethodMetadata * authMethodMetadata(const QString &authMethodKey)
Gets authentication method metadata via its key.
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
bool isValid(bool validateid=false) const
Whether the configuration is valid.
QString method() const
Textual key of the associated authentication method.
Definition: qgsauthconfig.h:78
const QString uri() const
A URI to auto-select a config when connecting to a resource.
Definition: qgsauthconfig.h:74
void setName(const QString &name)
Sets name of configuration.
Definition: qgsauthconfig.h:71
void setConfigMap(const QgsStringMap &map)
Set extended configuration map.
void setVersion(int version)
Sets version of the configuration.
Definition: qgsauthconfig.h:84
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
QgsStringMap configMap() const
Gets extended configuration, mapped to key/value pairs of QStrings.
void setMethod(const QString &method)
Definition: qgsauthconfig.h:79
void setUri(const QString &uri)
Definition: qgsauthconfig.h:75
void setId(const QString &id)
Sets auth config ID.
Definition: qgsauthconfig.h:66
Abstract base class for the edit widget of authentication method plugins.
virtual bool validateConfig()=0
Validate the configuration of subclasses.
void validityChanged(bool valid)
Emitted when the configuration validatity changes.
virtual void clearConfig()=0
Clear GUI controls in subclassed widget.
virtual QgsStringMap configMap() const =0
The configuration key-vale map of subclasses.
virtual void loadConfig(const QgsStringMap &configmap)=0
Load an existing config map into subclassed widget.
Holds data auth method key, description, and associated shared library file information.
QString description() const
Returns descriptive text for the method.
Abstract base class for authentication method plugins.
Definition: qgsauthmethod.h:39
int version() const
Increment this if method is significantly updated, allow updater code to be written for previously st...
Definition: qgsauthmethod.h:74
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:194
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugError(str)
Definition: qgslogger.h:38