31#include <QGlobalStatic>
33QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
40static QString invalidStyle_(
const QString &selector = QStringLiteral(
"QLineEdit" ) )
42 return QStringLiteral(
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
46 : QDialog( parent, fl )
50 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
51 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
52 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
55 this, &QgsCredentialDialog::requestCredentials,
56 Qt::BlockingQueuedConnection );
58 this, &QgsCredentialDialog::requestCredentialsMasterPassword,
59 Qt::BlockingQueuedConnection );
62 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
63 QMenu *menu =
new QMenu( mIgnoreButton );
64 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
65 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
66 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
67 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
68 menu->addAction( ignoreTemporarily );
69 menu->addAction( ignoreForSession );
70 connect( ignoreTemporarily, &QAction::triggered,
this, [ = ]
72 mIgnoreMode = IgnoreTemporarily;
73 mIgnoreButton->setText( ignoreTemporarily->text() );
74 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
76 connect( ignoreForSession, &QAction::triggered,
this, [ = ]
78 mIgnoreMode = IgnoreForSession;
79 mIgnoreButton->setText( ignoreForSession->text() );
80 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
82 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
83 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
84 mIgnoreButton->setMenu( menu );
85 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
88 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
89 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
92 connect( mIgnoreButton, &QPushButton::clicked,
this, [ = ](
bool )
94 const QString realm { mRealm };
96 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
98 sIgnoredConnectionsCache->insert( realm );
100 if ( mIgnoreMode == IgnoreTemporarily )
102 QTimer::singleShot( 10000,
nullptr, [ = ]()
104 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
105 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
106 sIgnoredConnectionsCache->remove( realm );
112 leMasterPass->setPlaceholderText( tr(
"Required" ) );
113 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
115 leUsername->setFocus();
121 if ( qApp->thread() != QThread::currentThread() )
123 QgsDebugMsg( QStringLiteral(
"emitting signal" ) );
125 QgsDebugMsg( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ) );
129 requestCredentials( realm, &username, &password, message, &ok );
134void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
136 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
139 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
140 if ( sIgnoredConnectionsCache->contains( realm ) )
142 QgsDebugMsg( QStringLiteral(
"Skipping ignored connection: " ) + realm );
147 stackedWidget->setCurrentIndex( 0 );
148 mIgnoreButton->show();
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 QString removePassword(const QString &aUri)
Removes the password element from a URI.
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)