QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 = "QLineEdit" )
28 {
29  return QString( "%1{color: rgb(200, 0, 0);}" ).arg( selector );
30 }
31 
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 
50 {
51 }
52 
53 bool QgsCredentialDialog::request( const QString& realm, QString &username, QString &password, const QString& message )
54 {
55  bool ok;
56  if ( qApp->thread() != QThread::currentThread() )
57  {
58  QgsDebugMsg( "emitting signal" );
59  emit credentialsRequested( realm, &username, &password, message, &ok );
60  QgsDebugMsg( QString( "signal returned %1 (username=%2, password=%3)" ).arg( ok ? "true" : "false", username, password ) );
61  }
62  else
63  {
64  requestCredentials( realm, &username, &password, message, &ok );
65  }
66  return ok;
67 }
68 
69 void QgsCredentialDialog::requestCredentials( const QString& realm, QString *username, QString *password, const QString& message, bool *ok )
70 {
71  Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
72  QgsDebugMsg( "Entering." );
73  stackedWidget->setCurrentIndex( 0 );
74 
75  labelRealm->setText( realm );
76  leUsername->setText( *username );
77  lePassword->setText( *password );
78  labelMessage->setText( message );
79  labelMessage->setHidden( message.isEmpty() );
80 
81  if ( !leUsername->text().isEmpty() )
82  lePassword->setFocus();
83 
84  QWidget *activeWindow = qApp->activeWindow();
85 
86  QApplication::setOverrideCursor( Qt::ArrowCursor );
87 
88  QgsDebugMsg( "exec()" );
89  *ok = exec() == QDialog::Accepted;
90  QgsDebugMsg( QString( "exec(): %1" ).arg( *ok ? "true" : "false" ) );
91 
93 
94  if ( activeWindow )
95  activeWindow->raise();
96 
97  if ( *ok )
98  {
99  *username = leUsername->text();
100  *password = lePassword->text();
101  }
102 }
103 
105 {
106  bool ok;
107  if ( qApp->thread() != QThread::currentThread() )
108  {
109  QgsDebugMsg( "emitting signal" );
110  emit credentialsRequestedMasterPassword( &password, stored, &ok );
111  }
112  else
113  {
114  requestCredentialsMasterPassword( &password, stored, &ok );
115  }
116  return ok;
117 }
118 
119 void QgsCredentialDialog::requestCredentialsMasterPassword( QString * password, bool stored , bool *ok )
120 {
121  QgsDebugMsg( "Entering." );
122  stackedWidget->setCurrentIndex( 1 );
123  leMasterPass->setFocus();
124 
125  QString titletxt( stored ? tr( "Enter CURRENT master authentication password" ) : tr( "Set NEW master authentication password" ) );
126  lblPasswordTitle->setText( titletxt );
127 
128  leMasterPassVerify->setVisible( !stored );
129  lblDontForget->setVisible( !stored );
130 
131  QApplication::setOverrideCursor( Qt::ArrowCursor );
132 
133  grpbxPassAttempts->setVisible( false );
134  int passfailed = 0;
135  while ( true )
136  {
137  mOkButton->setEnabled( false );
138  // TODO: have the number of attempted passwords configurable in auth settings?
139  if ( passfailed >= 3 )
140  {
141  lblSavedForSession->setVisible( false );
142  grpbxPassAttempts->setTitle( tr( "Password attempts: %1" ).arg( passfailed ) );
143  grpbxPassAttempts->setVisible( true );
144  }
145 
146  // resize vertically to fit contents
147  QSize s = sizeHint();
148  s.setWidth( width() );
149  resize( s );
150 
151  QgsDebugMsg( "exec()" );
152  *ok = exec() == QDialog::Accepted;
153  QgsDebugMsg( QString( "exec(): %1" ).arg( *ok ? "true" : "false" ) );
154 
155  if ( *ok )
156  {
157  bool passok = !leMasterPass->text().isEmpty();
158  if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
159  {
160  passok = QgsAuthManager::instance()->verifyMasterPassword( leMasterPass->text() );
161  }
162 
163  if ( passok && !stored )
164  {
165  passok = ( leMasterPass->text() == leMasterPassVerify->text() );
166  }
167 
168  if ( passok || chkbxEraseAuthDb->isChecked() )
169  {
170  if ( stored && chkbxEraseAuthDb->isChecked() )
171  {
173  }
174  else
175  {
176  *password = leMasterPass->text();
177  }
178  break;
179  }
180  else
181  {
182  if ( stored )
183  ++passfailed;
184 
185  leMasterPass->setStyleSheet( invalidStyle_() );
186  if ( leMasterPassVerify->isVisible() )
187  {
188  leMasterPassVerify->setStyleSheet( invalidStyle_() );
189  }
190  }
191  }
192  else
193  {
194  break;
195  }
196 
197  if ( passfailed >= 5 )
198  {
199  break;
200  }
201  }
202 
203  // don't leave master password in singleton's text field, or the ability to show it
204  leMasterPass->clear();
205  chkMasterPassShow->setChecked( false );
206  leMasterPassVerify->clear();
207 
208  chkbxEraseAuthDb->setChecked( false );
209  lblSavedForSession->setVisible( true );
210 
211  // re-enable OK button or non-master-password requests will be blocked
212  // needs to come after leMasterPass->clear() or textChanged auto-slot with disable it again
213  mOkButton->setEnabled( true );
214 
216 
217  if ( passfailed >= 5 )
218  {
219  close();
220  }
221 }
222 
223 void QgsCredentialDialog::on_chkMasterPassShow_stateChanged( int state )
224 {
225  leMasterPass->setEchoMode(( state > 0 ) ? QLineEdit::Normal : QLineEdit::Password );
226  leMasterPassVerify->setEchoMode(( state > 0 ) ? QLineEdit::Normal : QLineEdit::Password );
227 }
228 
229 void QgsCredentialDialog::on_leMasterPass_textChanged( const QString &pass )
230 {
231  leMasterPass->setStyleSheet( "" );
232  bool passok = !pass.isEmpty(); // regardless of new or comparing existing, empty password disallowed
233  if ( leMasterPassVerify->isVisible() )
234  {
235  leMasterPassVerify->setStyleSheet( "" );
236  passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
237  }
238  mOkButton->setEnabled( passok );
239 
240  if ( leMasterPassVerify->isVisible() && !passok )
241  {
242  leMasterPass->setStyleSheet( invalidStyle_() );
243  leMasterPassVerify->setStyleSheet( invalidStyle_() );
244  }
245 }
246 
247 void QgsCredentialDialog::on_leMasterPassVerify_textChanged( const QString &pass )
248 {
249  if ( leMasterPassVerify->isVisible() )
250  {
251  leMasterPass->setStyleSheet( "" );
252  leMasterPassVerify->setStyleSheet( "" );
253 
254  // empty password disallowed
255  bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
256  mOkButton->setEnabled( passok );
257  if ( !passok )
258  {
259  leMasterPass->setStyleSheet( invalidStyle_() );
260  leMasterPassVerify->setStyleSheet( invalidStyle_() );
261  }
262  }
263 }
264 
265 void QgsCredentialDialog::on_chkbxEraseAuthDb_toggled( bool checked )
266 {
267  if ( checked )
268  mOkButton->setEnabled( true );
269 }
270 
bool close()
void setupUi(QWidget *widget)
static QgsAuthManager * instance()
Enforce singleton pattern.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
int exec()
QgsCredentialDialog(QWidget *parent=nullptr, const Qt::WindowFlags &fl=QgisGui::ModalDialogFlags)
QThread * thread() const
QString tr(const char *sourceText, const char *disambiguation, int n)
void clear()
int width() const
void resize(int w, int h)
void setEnabled(bool)
void credentialsRequested(const QString &, QString *, QString *, const QString &, bool *)
void setFocus()
void setWidth(int width)
void raise()
bool isEmpty() const
static QString invalidStyle_(const QString &selector="QLineEdit")
void setOverrideCursor(const QCursor &cursor)
virtual bool request(const QString &realm, QString &username, QString &password, const QString &message=QString::null) override
request a password
void restoreOverrideCursor()
virtual QSize sizeHint() const
void setScheduledAuthDbErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
QThread * currentThread()
bool verifyMasterPassword(const QString &compare=QString::null)
Verify the supplied master password against any existing hash in authentication database.
typedef WindowFlags
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual bool requestMasterPassword(QString &password, bool stored=false) override
request a master password
void credentialsRequestedMasterPassword(QString *, bool, bool *)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setInstance(QgsCredentials *theInstance)
register instance