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