25 #include <QPushButton>
27 #include <QToolButton>
30 #include <QGlobalStatic>
32 QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
39 static QString invalidStyle_(
const QString &selector = QStringLiteral(
"QLineEdit" ) )
41 return QStringLiteral(
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
45 : QDialog( parent, fl )
49 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
50 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
51 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
54 this, &QgsCredentialDialog::requestCredentials,
55 Qt::BlockingQueuedConnection );
57 this, &QgsCredentialDialog::requestCredentialsMasterPassword,
58 Qt::BlockingQueuedConnection );
61 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
62 QMenu *menu =
new QMenu( mIgnoreButton );
63 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
64 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
65 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
66 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
67 menu->addAction( ignoreTemporarily );
68 menu->addAction( ignoreForSession );
69 connect( ignoreTemporarily, &QAction::triggered,
this, [ = ]
71 mIgnoreMode = IgnoreTemporarily;
72 mIgnoreButton->setText( ignoreTemporarily->text() );
73 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
75 connect( ignoreForSession, &QAction::triggered,
this, [ = ]
77 mIgnoreMode = IgnoreForSession;
78 mIgnoreButton->setText( ignoreForSession->text() );
79 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
81 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
82 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
83 mIgnoreButton->setMenu( menu );
84 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
87 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
88 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
91 connect( mIgnoreButton, &QPushButton::clicked,
this, [ = ](
bool )
93 const QString realm { labelRealm->text() };
95 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
97 sIgnoredConnectionsCache->insert( realm );
99 if ( mIgnoreMode == IgnoreTemporarily )
101 QTimer::singleShot( 10000,
nullptr, [ = ]()
103 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
104 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
105 sIgnoredConnectionsCache->remove( realm );
111 leMasterPass->setPlaceholderText( tr(
"Required" ) );
112 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
114 leUsername->setFocus();
120 if ( qApp->thread() != QThread::currentThread() )
122 QgsDebugMsg( QStringLiteral(
"emitting signal" ) );
124 QgsDebugMsg( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ) );
128 requestCredentials( realm, &username, &password, message, &ok );
133 void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
135 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
138 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
139 if ( sIgnoredConnectionsCache->contains( realm ) )
141 QgsDebugMsg( QStringLiteral(
"Skipping ignored connection: " ) + realm );
146 stackedWidget->setCurrentIndex( 0 );
147 mIgnoreButton->show();
149 labelRealm->setText( realm );
150 leUsername->setText( *username );
151 lePassword->setText( *password );
152 labelMessage->setText( message );
153 labelMessage->setHidden( message.isEmpty() );
155 if ( leUsername->text().isEmpty() )
156 leUsername->setFocus();
158 lePassword->setFocus();
160 QWidget *activeWindow = qApp->activeWindow();
162 QApplication::setOverrideCursor( Qt::ArrowCursor );
165 *ok = exec() == QDialog::Accepted;
166 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
168 QApplication::restoreOverrideCursor();
171 activeWindow->raise();
175 *username = leUsername->text();
176 *password = lePassword->text();
183 if ( qApp->thread() != QThread::currentThread() )
190 requestCredentialsMasterPassword( &password, stored, &ok );
195 void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
198 stackedWidget->setCurrentIndex( 1 );
200 mIgnoreButton->hide();
201 leMasterPass->setFocus();
203 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
204 lblPasswordTitle->setText( titletxt );
208 leMasterPassVerify->setVisible( !stored );
209 lblDontForget->setVisible( !stored );
211 QApplication::setOverrideCursor( Qt::ArrowCursor );
213 grpbxPassAttempts->setVisible(
false );
217 mOkButton->setEnabled(
false );
219 if ( passfailed >= 3 )
221 lblSavedForSession->setVisible(
false );
222 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
223 grpbxPassAttempts->setVisible(
true );
227 QSize s = sizeHint();
228 s.setWidth( width() );
232 *ok = exec() == QDialog::Accepted;
233 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
237 bool passok = !leMasterPass->text().isEmpty();
238 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
243 if ( passok && !stored )
245 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
248 if ( passok || chkbxEraseAuthDb->isChecked() )
250 if ( stored && chkbxEraseAuthDb->isChecked() )
256 *password = leMasterPass->text();
270 leMasterPass->setStyleSheet( invalidStyle_() );
271 if ( leMasterPassVerify->isVisible() )
273 leMasterPassVerify->setStyleSheet( invalidStyle_() );
282 if ( passfailed >= 5 )
289 leMasterPass->clear();
290 leMasterPassVerify->clear();
292 chkbxEraseAuthDb->setChecked(
false );
293 lblSavedForSession->setVisible(
true );
297 mOkButton->setEnabled(
true );
299 QApplication::restoreOverrideCursor();
301 if ( passfailed >= 5 )
307 void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
309 leMasterPass->setStyleSheet( QString() );
310 bool passok = !pass.isEmpty();
311 if ( leMasterPassVerify->isVisible() )
313 leMasterPassVerify->setStyleSheet( QString() );
314 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
316 mOkButton->setEnabled( passok );
318 if ( leMasterPassVerify->isVisible() && !passok )
320 leMasterPass->setStyleSheet( invalidStyle_() );
321 leMasterPassVerify->setStyleSheet( invalidStyle_() );
325 void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
327 if ( leMasterPassVerify->isVisible() )
329 leMasterPass->setStyleSheet( QString() );
330 leMasterPassVerify->setStyleSheet( QString() );
333 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
334 mOkButton->setEnabled( passok );
337 leMasterPass->setStyleSheet( invalidStyle_() );
338 leMasterPassVerify->setStyleSheet( invalidStyle_() );
343 void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
346 mOkButton->setEnabled(
true );