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