QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsauthguiutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsauthutils.cpp
3  ---------------------
4  begin : October 24, 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 "qgsauthguiutils.h"
18 
19 #include <QFileDialog>
20 #include <QInputDialog>
21 #include <QLineEdit>
22 #include <QMessageBox>
23 
24 #include "qgssettings.h"
25 #include "qgsauthmanager.h"
27 #include "qgslogger.h"
28 #include "qgsmessagebar.h"
29 #include "qgsapplication.h"
30 
31 
33 {
34  return QColor( 0, 170, 0 );
35 }
36 
38 {
39  return QColor( 255, 128, 0 );
40 }
41 
43 {
44  return QColor( 200, 0, 0 );
45 }
46 
48 {
49  return QColor( 255, 255, 125 );
50 }
51 
52 QString QgsAuthGuiUtils::greenTextStyleSheet( const QString &selector )
53 {
54  return QStringLiteral( "%1{color: %2;}" ).arg( selector, QgsAuthGuiUtils::greenColor().name() );
55 }
56 
57 QString QgsAuthGuiUtils::orangeTextStyleSheet( const QString &selector )
58 {
59  return QStringLiteral( "%1{color: %2;}" ).arg( selector, QgsAuthGuiUtils::orangeColor().name() );
60 }
61 
62 QString QgsAuthGuiUtils::redTextStyleSheet( const QString &selector )
63 {
64  return QStringLiteral( "%1{color: %2;}" ).arg( selector, QgsAuthGuiUtils::redColor().name() );
65 }
66 
68 {
70  {
71  msgbar->pushMessage( QObject::tr( "Authentication System" ),
72  QObject::tr( "DISABLED. Resources authenticating via the system can not be accessed" ),
73  Qgis::MessageLevel::Critical );
74  return true;
75  }
76  return false;
77 }
78 
79 void QgsAuthGuiUtils::exportSelectedAuthenticationConfigs( QStringList authenticationConfigIds, QgsMessageBar *msgbar )
80 {
81  const QString password = QInputDialog::getText( msgbar, QObject::tr( "Export Authentication Configurations" ),
82  QObject::tr( "Enter a password encrypt the configuration file:" ), QLineEdit::Password );
83  if ( password.isEmpty() )
84  {
85  if ( QMessageBox::warning( msgbar,
86  QObject::tr( "Export Authentication Configurations" ),
87  QObject::tr( "Exporting authentication configurations with a blank password will result in a plain text file which may contain sensitive information. Are you sure you want to do this?" ),
88  QMessageBox::Ok | QMessageBox::Cancel,
89  QMessageBox::Cancel ) == QMessageBox::Cancel )
90  {
91  return;
92  }
93  }
94 
95  const QString filename = QFileDialog::getSaveFileName( msgbar, QObject::tr( "Export Authentication Configurations" ), QDir::homePath(),
96  QObject::tr( "XML files (*.xml *.XML)" ) );
97  if ( filename.isEmpty() )
98  return;
99 
100  const bool ok = QgsApplication::authManager()->exportAuthenticationConfigsToXml( filename, authenticationConfigIds, password );
101  if ( !ok )
102  {
103  msgbar->pushMessage( QgsApplication::authManager()->authManTag(),
104  QObject::tr( "Export of authentication configurations failed." ),
105  Qgis::MessageLevel::Critical );
106  }
107 }
108 
110 {
111 
112  const QString filename = QFileDialog::getOpenFileName( msgbar, QObject::tr( "Export Authentication Configurations" ), QDir::homePath(),
113  QObject::tr( "XML files (*.xml *.XML)" ) );
114  if ( filename.isEmpty() )
115  return;
116 
117 
118  QFile file( filename );
119  if ( !file.open( QFile::ReadOnly ) )
120  {
121  return;
122  }
123 
124  QDomDocument document( QStringLiteral( "qgis_authentication" ) );
125  if ( !document.setContent( &file ) )
126  {
127  file.close();
128  return;
129  }
130  file.close();
131 
132  const QDomElement root = document.documentElement();
133  if ( root.tagName() != QLatin1String( "qgis_authentication" ) )
134  {
135  return;
136  }
137 
138  QString password;
139  if ( root.hasAttribute( QStringLiteral( "salt" ) ) )
140  {
141  password = QInputDialog::getText( msgbar, QObject::tr( "Import Authentication Configurations" ),
142  QObject::tr( "Enter the password to decrypt the configurations file:" ), QLineEdit::Password );
143  }
144 
145  const bool ok = QgsApplication::authManager()->importAuthenticationConfigsFromXml( filename, password );
146  if ( !ok )
147  {
148  msgbar->pushMessage( QgsApplication::authManager()->authManTag(),
149  QObject::tr( "Import of authentication configurations failed." ),
150  Qgis::MessageLevel::Critical );
151  }
152 }
153 
155 {
156  if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
157  return;
158 
159  if ( QgsApplication::authManager()->masterPasswordIsSet() )
160  {
161  msgbar->pushMessage( QgsApplication::authManager()->authManTag(),
162  QObject::tr( "Master password already set." ),
163  Qgis::MessageLevel::Info );
164  return;
165  }
167 }
168 
170 {
171  if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
172  return;
173 
174  QString msg( QObject::tr( "Master password not cleared because it is not set." ) );
175  Qgis::MessageLevel level( Qgis::MessageLevel::Info );
176 
177  if ( QgsApplication::authManager()->masterPasswordIsSet() )
178  {
180  msg = QObject::tr( "Master password cleared (NOTE: network connections may be cached)." );
181  if ( QgsApplication::authManager()->masterPasswordIsSet() )
182  {
183  msg = QObject::tr( "Master password FAILED to be cleared." );
184  level = Qgis::MessageLevel::Warning;
185  }
186  }
187 
188  msgbar->pushMessage( QgsApplication::authManager()->authManTag(), msg, level );
189 }
190 
191 void QgsAuthGuiUtils::resetMasterPassword( QgsMessageBar *msgbar, QWidget *parent )
192 {
193  if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
194  return;
195 
196  QString msg( QObject::tr( "Master password reset" ) );
197  Qgis::MessageLevel level( Qgis::MessageLevel::Info );
198 
199  // check that a master password is even set in auth db
200  if ( !QgsApplication::authManager()->masterPasswordHashInDatabase() )
201  {
202  msg = QObject::tr( "Master password reset: NO current password hash in database" );
203  msgbar->pushMessage( QgsApplication::authManager()->authManTag(), msg, Qgis::MessageLevel::Warning );
204  return;
205  }
206 
207  // get new password via dialog; do current password verification in-dialog
208  QString newpass;
209  QString oldpass;
210  bool keepbackup = false;
211  QgsMasterPasswordResetDialog dlg( parent );
212 
213  if ( !dlg.requestMasterPasswordReset( &newpass, &oldpass, &keepbackup ) )
214  {
215  QgsDebugMsg( QStringLiteral( "Master password reset: input canceled by user" ) );
216  return;
217  }
218 
219  QString backuppath;
220  if ( !QgsApplication::authManager()->resetMasterPassword( newpass, oldpass, keepbackup, &backuppath ) )
221  {
222  msg = QObject::tr( "Master password FAILED to be reset" );
223  level = Qgis::MessageLevel::Warning;
224  }
225 
226  if ( !backuppath.isEmpty() )
227  {
228  msg += QObject::tr( " (database backup: %1)" ).arg( backuppath );
229  }
230 
231  msgbar->pushMessage( QgsApplication::authManager()->authManTag(), msg, level );
232 }
233 
235 {
236  if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
237  return;
238 
240  const QString msg = QObject::tr( "Cached authentication configurations for session cleared" );
241  msgbar->pushMessage( QgsApplication::authManager()->authManTag(), msg, Qgis::MessageLevel::Info );
242 }
243 
245 {
246  if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
247  return;
248 
249  if ( QMessageBox::warning( parent,
250  QObject::tr( "Remove Configurations" ),
251  QObject::tr( "Are you sure you want to remove ALL authentication configurations?\n\n"
252  "Operation can NOT be undone!" ),
253  QMessageBox::Ok | QMessageBox::Cancel,
254  QMessageBox::Cancel ) == QMessageBox::Cancel )
255  {
256  return;
257  }
258 
259  QString msg( QObject::tr( "Authentication configurations removed." ) );
260  Qgis::MessageLevel level( Qgis::MessageLevel::Info );
261 
262  if ( !QgsApplication::authManager()->removeAllAuthenticationConfigs() )
263  {
264  msg = QObject::tr( "Authentication configurations FAILED to be removed." );
265  level = Qgis::MessageLevel::Warning;
266  }
267 
268  msgbar->pushMessage( QgsApplication::authManager()->authManTag(), msg, level );
269 }
270 
272 {
273  if ( QgsAuthGuiUtils::isDisabled( msgbar ) )
274  return;
275 
276  const QMessageBox::StandardButton btn = QMessageBox::warning(
277  parent,
278  QObject::tr( "Erase Database" ),
279  QObject::tr( "Are you sure you want to ERASE the entire authentication database?\n\n"
280  "Operation can NOT be undone!\n\n"
281  "(Current database will be backed up and new one created.)" ),
282  QMessageBox::Ok | QMessageBox::Cancel,
283  QMessageBox::Cancel );
284 
286 
287  if ( btn == QMessageBox::Cancel )
288  {
289  return;
290  }
291 
292  QString msg( QObject::tr( "Active authentication database erased." ) );
293  Qgis::MessageLevel level( Qgis::MessageLevel::Warning );
294 
295  QString backuppath;
296  if ( !QgsApplication::authManager()->eraseAuthenticationDatabase( true, &backuppath ) )
297  {
298  msg = QObject::tr( "Authentication database FAILED to be erased." );
299  level = Qgis::MessageLevel::Warning;
300  }
301  else
302  {
303  if ( !backuppath.isEmpty() )
304  {
305  msg += QObject::tr( " (backup: %1)" ).arg( backuppath );
306  }
307  level = Qgis::MessageLevel::Critical;
308  }
309 
310  msgbar->pushMessage( QObject::tr( "RESTART QGIS" ), msg, level );
311 }
312 
313 void QgsAuthGuiUtils::fileFound( bool found, QWidget *widget )
314 {
315  if ( !found )
316  {
317  widget->setStyleSheet( QgsAuthGuiUtils::redTextStyleSheet( QStringLiteral( "QLineEdit" ) ) );
318  widget->setToolTip( QObject::tr( "File not found" ) );
319  }
320  else
321  {
322  widget->setStyleSheet( QString() );
323  widget->setToolTip( QString() );
324  }
325 }
326 
327 QString QgsAuthGuiUtils::getOpenFileName( QWidget *parent, const QString &title, const QString &extfilter )
328 {
329  QgsSettings settings;
330  const QString recentdir = settings.value( QStringLiteral( "UI/lastAuthOpenFileDir" ), QDir::homePath() ).toString();
331  QString f = QFileDialog::getOpenFileName( parent, title, recentdir, extfilter );
332  if ( !f.isEmpty() )
333  {
334  settings.setValue( QStringLiteral( "UI/lastAuthOpenFileDir" ), QFileInfo( f ).absoluteDir().path() );
335  }
336  return f;
337 }
338 
339 void QgsAuthGuiUtils::passwordHelperDelete( QgsMessageBar *msgbar, QWidget *parent )
340 {
341  if ( QMessageBox::warning( parent,
342  QObject::tr( "Delete Password" ),
343  QObject::tr( "Do you really want to delete the master password from your %1?" )
345  QMessageBox::Ok | QMessageBox::Cancel,
346  QMessageBox::Cancel ) == QMessageBox::Cancel )
347  {
348  return;
349  }
350  QString msg;
351  Qgis::MessageLevel level;
353  {
355  level = Qgis::MessageLevel::Warning;
356  }
357  else
358  {
359  msg = QObject::tr( "Master password was successfully deleted from your %1" )
361 
362  level = Qgis::MessageLevel::Info;
363  }
364  msgbar->pushMessage( QObject::tr( "Password helper delete" ), msg, level );
365 }
366 
368 {
369  QString msg;
370  Qgis::MessageLevel level;
371  if ( ! QgsApplication::authManager()->masterPasswordIsSet() )
372  {
373  msg = QObject::tr( "Master password is not set and cannot be stored in your %1." )
375  level = Qgis::MessageLevel::Warning;
376  }
378  {
380  level = Qgis::MessageLevel::Warning;
381  }
382  else
383  {
384  msg = QObject::tr( "Master password has been successfully stored in your %1." )
386 
387  level = Qgis::MessageLevel::Info;
388  }
389  msgbar->pushMessage( QObject::tr( "Password helper write" ), msg, level );
390 }
391 
393 {
395  const QString msg = enabled ? QObject::tr( "Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
397  QObject::tr( "Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
399  msgbar->pushMessage( QObject::tr( "Password helper write" ), msg, Qgis::MessageLevel::Info );
400 }
401 
402 void QgsAuthGuiUtils::passwordHelperLoggingEnable( bool enabled, QgsMessageBar *msgbar, int timeout )
403 {
404  Q_UNUSED( msgbar )
405  Q_UNUSED( timeout )
407 }
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:106
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static void importAuthenticationConfigs(QgsMessageBar *msgbar)
Import authentication configurations from a XML file.
static void exportSelectedAuthenticationConfigs(QStringList authenticationConfigIds, QgsMessageBar *msgbar)
Exports selected authentication configurations to a XML file.
static QString greenTextStyleSheet(const QString &selector="*")
Green text stylesheet representing valid, trusted, etc. certificate.
static void resetMasterPassword(QgsMessageBar *msgbar, QWidget *parent=nullptr)
Reset the cached master password, updating its hash in authentication database and resetting all exis...
static QColor greenColor()
Green color representing valid, trusted, etc. certificate.
static QColor orangeColor()
Orange color representing loaded component, but not stored in database.
static QString redTextStyleSheet(const QString &selector="*")
Red text stylesheet representing invalid, untrusted, etc. certificate.
static void clearCachedMasterPassword(QgsMessageBar *msgbar)
Clear the currently cached master password (not its hash in database)
static void passwordHelperEnable(bool enabled, QgsMessageBar *msgbar)
Sets password helper enabled (enable/disable)
static QString orangeTextStyleSheet(const QString &selector="*")
Orange text stylesheet representing loaded component, but not stored in database.
static void clearCachedAuthenticationConfigs(QgsMessageBar *msgbar)
Clear all cached authentication configs for session.
static bool isDisabled(QgsMessageBar *msgbar)
Verify the authentication system is active, else notify user.
static void passwordHelperLoggingEnable(bool enabled, QgsMessageBar *msgbar, int timeout=0)
Sets password helper logging enabled (enable/disable)
static void eraseAuthenticationDatabase(QgsMessageBar *msgbar, QWidget *parent=nullptr)
Completely clear out the authentication database (configs and master password)
static void removeAuthenticationConfigs(QgsMessageBar *msgbar, QWidget *parent=nullptr)
Remove all authentication configs.
static QColor yellowColor()
Yellow color representing caution regarding action.
static void fileFound(bool found, QWidget *widget)
Color a widget via a stylesheet if a file path is found or not.
static void setMasterPassword(QgsMessageBar *msgbar)
Sets the cached master password (and verifies it if its hash is in authentication database)
static QString getOpenFileName(QWidget *parent, const QString &title, const QString &extfilter)
Open file dialog for auth associated widgets.
static void passwordHelperDelete(QgsMessageBar *msgbar, QWidget *parent=nullptr)
Remove master password from wallet.
static void passwordHelperSync(QgsMessageBar *msgbar)
Store master password into the wallet.
static QColor redColor()
Red color representing invalid, untrusted, etc. certificate.
void clearAllCachedConfigs()
Clear all authentication configs from authentication method caches.
bool exportAuthenticationConfigsToXml(const QString &filename, const QStringList &authcfgs, const QString &password=QString())
Export authentication configurations to an XML file.
void setPasswordHelperEnabled(bool enabled)
Password helper enabled setter.
void setScheduledAuthDatabaseErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
bool importAuthenticationConfigsFromXml(const QString &filename, const QString &password=QString(), bool overwrite=false)
Import authentication configurations from an XML file.
void clearMasterPassword()
Clear supplied master password.
const QString passwordHelperErrorMessage()
Error message getter.
void setPasswordHelperLoggingEnabled(bool enabled)
Password helper logging enabled setter.
bool setMasterPassword(bool verify=false)
Main call to initially set or continually check master password is set.
static const QString AUTH_PASSWORD_HELPER_DISPLAY_NAME
The display name of the password helper (platform dependent)
Dialog to verify current master password and initiate reset of authentication database with a new pas...
bool requestMasterPasswordReset(QString *newpass, QString *oldpass, bool *keepbackup)
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38