QGIS API Documentation  2.99.0-Master (90ae728)
qgscredentialdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscredentialdialog.cpp - description
3  -------------------
4  begin : February 2010
5  copyright : (C) 2010 by Juergen E. Fischer
6  email : jef at norbit dot de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscredentialdialog.h"
19 
20 #include "qgsauthmanager.h"
21 #include "qgslogger.h"
22 
23 #include <QPushButton>
24 #include <QSettings>
25 #include <QThread>
26 
27 static QString invalidStyle_( const QString& selector = QStringLiteral( "QLineEdit" ) )
28 {
29  return QStringLiteral( "%1{color: rgb(200, 0, 0);}" ).arg( selector );
30 }
31 
32 QgsCredentialDialog::QgsCredentialDialog( QWidget *parent, Qt::WindowFlags fl )
33  : QDialog( parent, fl )
34  , mOkButton( nullptr )
35 {
36  setupUi( this );
37  setInstance( this );
38  connect( this, SIGNAL( credentialsRequested( QString, QString *, QString *, QString, bool * ) ),
39  this, SLOT( requestCredentials( QString, QString *, QString *, QString, bool * ) ),
40  Qt::BlockingQueuedConnection );
41  connect( this, SIGNAL( credentialsRequestedMasterPassword( QString *, bool, bool * ) ),
42  this, SLOT( requestCredentialsMasterPassword( QString *, bool, bool * ) ),
43  Qt::BlockingQueuedConnection );
44  mOkButton = buttonBox->button( QDialogButtonBox::Ok );
45  leMasterPass->setPlaceholderText( tr( "Required" ) );
46  leUsername->setFocus();
47 }
48 
49 bool QgsCredentialDialog::request( const QString& realm, QString &username, QString &password, const QString& message )
50 {
51  bool ok;
52  if ( qApp->thread() != QThread::currentThread() )
53  {
54  QgsDebugMsg( "emitting signal" );
55  emit credentialsRequested( realm, &username, &password, message, &ok );
56  QgsDebugMsg( QString( "signal returned %1 (username=%2, password=%3)" ).arg( ok ? "true" : "false", username, password ) );
57  }
58  else
59  {
60  requestCredentials( realm, &username, &password, message, &ok );
61  }
62  return ok;
63 }
64 
65 void QgsCredentialDialog::requestCredentials( const QString& realm, QString *username, QString *password, const QString& message, bool *ok )
66 {
67  Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
68  QgsDebugMsg( "Entering." );
69  stackedWidget->setCurrentIndex( 0 );
70 
71  labelRealm->setText( realm );
72  leUsername->setText( *username );
73  lePassword->setText( *password );
74  labelMessage->setText( message );
75  labelMessage->setHidden( message.isEmpty() );
76 
77  if ( !leUsername->text().isEmpty() )
78  lePassword->setFocus();
79 
80  QWidget *activeWindow = qApp->activeWindow();
81 
82  QApplication::setOverrideCursor( Qt::ArrowCursor );
83 
84  QgsDebugMsg( "exec()" );
85  *ok = exec() == QDialog::Accepted;
86  QgsDebugMsg( QString( "exec(): %1" ).arg( *ok ? "true" : "false" ) );
87 
88  QApplication::restoreOverrideCursor();
89 
90  if ( activeWindow )
91  activeWindow->raise();
92 
93  if ( *ok )
94  {
95  *username = leUsername->text();
96  *password = lePassword->text();
97  }
98 }
99 
100 bool QgsCredentialDialog::requestMasterPassword( QString &password , bool stored )
101 {
102  bool ok;
103  if ( qApp->thread() != QThread::currentThread() )
104  {
105  QgsDebugMsg( "emitting signal" );
106  emit credentialsRequestedMasterPassword( &password, stored, &ok );
107  }
108  else
109  {
110  requestCredentialsMasterPassword( &password, stored, &ok );
111  }
112  return ok;
113 }
114 
115 void QgsCredentialDialog::requestCredentialsMasterPassword( QString * password, bool stored , bool *ok )
116 {
117  QgsDebugMsg( "Entering." );
118  stackedWidget->setCurrentIndex( 1 );
119  leMasterPass->setFocus();
120 
121  QString titletxt( stored ? tr( "Enter CURRENT master authentication password" ) : tr( "Set NEW master authentication password" ) );
122  lblPasswordTitle->setText( titletxt );
123 
124  leMasterPassVerify->setVisible( !stored );
125  lblDontForget->setVisible( !stored );
126 
127  QApplication::setOverrideCursor( Qt::ArrowCursor );
128 
129  grpbxPassAttempts->setVisible( false );
130  int passfailed = 0;
131  while ( true )
132  {
133  mOkButton->setEnabled( false );
134  // TODO: have the number of attempted passwords configurable in auth settings?
135  if ( passfailed >= 3 )
136  {
137  lblSavedForSession->setVisible( false );
138  grpbxPassAttempts->setTitle( tr( "Password attempts: %1" ).arg( passfailed ) );
139  grpbxPassAttempts->setVisible( true );
140  }
141 
142  // resize vertically to fit contents
143  QSize s = sizeHint();
144  s.setWidth( width() );
145  resize( s );
146 
147  QgsDebugMsg( "exec()" );
148  *ok = exec() == QDialog::Accepted;
149  QgsDebugMsg( QString( "exec(): %1" ).arg( *ok ? "true" : "false" ) );
150 
151  if ( *ok )
152  {
153  bool passok = !leMasterPass->text().isEmpty();
154  if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
155  {
156  passok = QgsAuthManager::instance()->verifyMasterPassword( leMasterPass->text() );
157  }
158 
159  if ( passok && !stored )
160  {
161  passok = ( leMasterPass->text() == leMasterPassVerify->text() );
162  }
163 
164  if ( passok || chkbxEraseAuthDb->isChecked() )
165  {
166  if ( stored && chkbxEraseAuthDb->isChecked() )
167  {
169  }
170  else
171  {
172  *password = leMasterPass->text();
173  }
174  break;
175  }
176  else
177  {
178  if ( stored )
179  ++passfailed;
180 
181  leMasterPass->setStyleSheet( invalidStyle_() );
182  if ( leMasterPassVerify->isVisible() )
183  {
184  leMasterPassVerify->setStyleSheet( invalidStyle_() );
185  }
186  }
187  }
188  else
189  {
190  break;
191  }
192 
193  if ( passfailed >= 5 )
194  {
195  break;
196  }
197  }
198 
199  // don't leave master password in singleton's text field, or the ability to show it
200  leMasterPass->clear();
201  chkMasterPassShow->setChecked( false );
202  leMasterPassVerify->clear();
203 
204  chkbxEraseAuthDb->setChecked( false );
205  lblSavedForSession->setVisible( true );
206 
207  // re-enable OK button or non-master-password requests will be blocked
208  // needs to come after leMasterPass->clear() or textChanged auto-slot with disable it again
209  mOkButton->setEnabled( true );
210 
211  QApplication::restoreOverrideCursor();
212 
213  if ( passfailed >= 5 )
214  {
215  close();
216  }
217 }
218 
219 void QgsCredentialDialog::on_chkMasterPassShow_stateChanged( int state )
220 {
221  leMasterPass->setEchoMode(( state > 0 ) ? QLineEdit::Normal : QLineEdit::Password );
222  leMasterPassVerify->setEchoMode(( state > 0 ) ? QLineEdit::Normal : QLineEdit::Password );
223 }
224 
225 void QgsCredentialDialog::on_leMasterPass_textChanged( const QString &pass )
226 {
227  leMasterPass->setStyleSheet( QLatin1String( "" ) );
228  bool passok = !pass.isEmpty(); // regardless of new or comparing existing, empty password disallowed
229  if ( leMasterPassVerify->isVisible() )
230  {
231  leMasterPassVerify->setStyleSheet( QLatin1String( "" ) );
232  passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
233  }
234  mOkButton->setEnabled( passok );
235 
236  if ( leMasterPassVerify->isVisible() && !passok )
237  {
238  leMasterPass->setStyleSheet( invalidStyle_() );
239  leMasterPassVerify->setStyleSheet( invalidStyle_() );
240  }
241 }
242 
243 void QgsCredentialDialog::on_leMasterPassVerify_textChanged( const QString &pass )
244 {
245  if ( leMasterPassVerify->isVisible() )
246  {
247  leMasterPass->setStyleSheet( QLatin1String( "" ) );
248  leMasterPassVerify->setStyleSheet( QLatin1String( "" ) );
249 
250  // empty password disallowed
251  bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
252  mOkButton->setEnabled( passok );
253  if ( !passok )
254  {
255  leMasterPass->setStyleSheet( invalidStyle_() );
256  leMasterPassVerify->setStyleSheet( invalidStyle_() );
257  }
258  }
259 }
260 
261 void QgsCredentialDialog::on_chkbxEraseAuthDb_toggled( bool checked )
262 {
263  if ( checked )
264  mOkButton->setEnabled( true );
265 }
266 
static QgsAuthManager * instance()
Enforce singleton pattern.
void setScheduledAuthDatabaseErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void setInstance(QgsCredentials *instance)
register instance
static QString invalidStyle_(const QString &selector=QStringLiteral("QLineEdit"))
QgsCredentialDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgisGui::ModalDialogFlags)
void credentialsRequested(const QString &, QString *, QString *, const QString &, bool *)
virtual bool request(const QString &realm, QString &username, QString &password, const QString &message=QString::null) override
request a password
bool verifyMasterPassword(const QString &compare=QString::null)
Verify the supplied master password against any existing hash in authentication database.
virtual bool requestMasterPassword(QString &password, bool stored=false) override
request a master password
void credentialsRequestedMasterPassword(QString *, bool, bool *)