30#include <QGlobalStatic>
32QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
39static QString invalidStyle_(
const QString &selector = QStringLiteral(
"QLineEdit" ) )
41 return QStringLiteral(
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
45 : QDialog( parent, fl )
51 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
52 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
53 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
56 this, &QgsCredentialDialog::requestCredentials,
57 Qt::BlockingQueuedConnection );
59 this, &QgsCredentialDialog::requestCredentialsMasterPassword,
60 Qt::BlockingQueuedConnection );
63 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
64 QMenu *menu =
new QMenu( mIgnoreButton );
65 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
66 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
67 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
68 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
69 menu->addAction( ignoreTemporarily );
70 menu->addAction( ignoreForSession );
71 connect( ignoreTemporarily, &QAction::triggered,
this, [ = ]
73 mIgnoreMode = IgnoreTemporarily;
74 mIgnoreButton->setText( ignoreTemporarily->text() );
75 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
77 connect( ignoreForSession, &QAction::triggered,
this, [ = ]
79 mIgnoreMode = IgnoreForSession;
80 mIgnoreButton->setText( ignoreForSession->text() );
81 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
83 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
84 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
85 mIgnoreButton->setMenu( menu );
86 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
89 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
90 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
93 connect( mIgnoreButton, &QPushButton::clicked,
this, [ = ](
bool )
95 const QString realm { labelRealm->text() };
97 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
99 sIgnoredConnectionsCache->insert( realm );
101 if ( mIgnoreMode == IgnoreTemporarily )
103 QTimer::singleShot( 10000,
nullptr, [ = ]()
105 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
106 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
107 sIgnoredConnectionsCache->remove( realm );
113 leMasterPass->setPlaceholderText( tr(
"Required" ) );
114 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
116 leUsername->setFocus();
122 if ( qApp->thread() != QThread::currentThread() )
124 QgsDebugMsg( QStringLiteral(
"emitting signal" ) );
126 QgsDebugMsg( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ) );
130 requestCredentials( realm, &username, &password, message, &ok );
135void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
137 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
140 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
141 if ( sIgnoredConnectionsCache->contains( realm ) )
143 QgsDebugMsg( QStringLiteral(
"Skipping ignored connection: " ) + realm );
148 stackedWidget->setCurrentIndex( 0 );
149 mIgnoreButton->show();
151 labelRealm->setText( realm );
152 leUsername->setText( *username );
153 lePassword->setText( *password );
154 labelMessage->setText( message );
155 labelMessage->setHidden( message.isEmpty() );
157 if ( leUsername->text().isEmpty() )
158 leUsername->setFocus();
160 lePassword->setFocus();
162 QWidget *activeWindow = qApp->activeWindow();
164 QApplication::setOverrideCursor( Qt::ArrowCursor );
167 *ok = exec() == QDialog::Accepted;
168 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
170 QApplication::restoreOverrideCursor();
173 activeWindow->raise();
177 *username = leUsername->text();
178 *password = lePassword->text();
185 if ( qApp->thread() != QThread::currentThread() )
192 requestCredentialsMasterPassword( &password, stored, &ok );
197void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
200 stackedWidget->setCurrentIndex( 1 );
202 mIgnoreButton->hide();
203 leMasterPass->setFocus();
205 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
206 lblPasswordTitle->setText( titletxt );
210 leMasterPassVerify->setVisible( !stored );
211 lblDontForget->setVisible( !stored );
213 QApplication::setOverrideCursor( Qt::ArrowCursor );
215 grpbxPassAttempts->setVisible(
false );
219 mOkButton->setEnabled(
false );
221 if ( passfailed >= 3 )
223 lblSavedForSession->setVisible(
false );
224 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
225 grpbxPassAttempts->setVisible(
true );
229 QSize s = sizeHint();
230 s.setWidth( width() );
234 *ok = exec() == QDialog::Accepted;
235 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
239 bool passok = !leMasterPass->text().isEmpty();
240 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
245 if ( passok && !stored )
247 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
250 if ( passok || chkbxEraseAuthDb->isChecked() )
252 if ( stored && chkbxEraseAuthDb->isChecked() )
258 *password = leMasterPass->text();
272 leMasterPass->setStyleSheet( invalidStyle_() );
273 if ( leMasterPassVerify->isVisible() )
275 leMasterPassVerify->setStyleSheet( invalidStyle_() );
284 if ( passfailed >= 5 )
291 leMasterPass->clear();
292 leMasterPassVerify->clear();
294 chkbxEraseAuthDb->setChecked(
false );
295 lblSavedForSession->setVisible(
true );
299 mOkButton->setEnabled(
true );
301 QApplication::restoreOverrideCursor();
303 if ( passfailed >= 5 )
309void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
311 leMasterPass->setStyleSheet( QString() );
312 bool passok = !pass.isEmpty();
313 if ( leMasterPassVerify->isVisible() )
315 leMasterPassVerify->setStyleSheet( QString() );
316 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
318 mOkButton->setEnabled( passok );
320 if ( leMasterPassVerify->isVisible() && !passok )
322 leMasterPass->setStyleSheet( invalidStyle_() );
323 leMasterPassVerify->setStyleSheet( invalidStyle_() );
327void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
329 if ( leMasterPassVerify->isVisible() )
331 leMasterPass->setStyleSheet( QString() );
332 leMasterPassVerify->setStyleSheet( QString() );
335 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
336 mOkButton->setEnabled( passok );
339 leMasterPass->setStyleSheet( invalidStyle_() );
340 leMasterPassVerify->setStyleSheet( invalidStyle_() );
345void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
348 mOkButton->setEnabled(
true );
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
bool verifyMasterPassword(const QString &compare=QString())
Verify the supplied master password against any existing hash in authentication database.
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 passwordHelperEnabled() const
Password helper enabled getter.
static const QString AUTH_PASSWORD_HELPER_DISPLAY_NAME
The display name of the password helper (platform dependent)
QgsCredentialDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
QgsCredentialDialog constructor.
bool requestMasterPassword(QString &password, bool stored=false) override
request a master password
bool request(const QString &realm, QString &username, QString &password, const QString &message=QString()) override
request a password
void credentialsRequested(const QString &, QString *, QString *, const QString &, bool *)
void credentialsRequestedMasterPassword(QString *, bool, bool *)
void setInstance(QgsCredentials *instance)
register instance
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...
Q_GLOBAL_STATIC(IgnoredConnectionsSet, sIgnoredConnectionsCache)
Temporary cache for ignored connections, to avoid GUI freezing by multiple credentials requests to th...
QSet< QString > IgnoredConnectionsSet
#define QgsDebugMsgLevel(str, level)