19#include "moc_qgscredentialdialog.cpp"
32#include <QGlobalStatic>
34QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
41static QString invalidStyle_(
const QString &selector = QStringLiteral(
"QLineEdit" ) )
43 return QStringLiteral(
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
47 : QDialog( parent, fl )
53 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
54 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
55 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
58 this, &QgsCredentialDialog::requestCredentials,
59 Qt::BlockingQueuedConnection );
61 this, &QgsCredentialDialog::requestCredentialsMasterPassword,
62 Qt::BlockingQueuedConnection );
65 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
66 QMenu *menu =
new QMenu( mIgnoreButton );
67 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
68 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
69 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
70 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
71 menu->addAction( ignoreTemporarily );
72 menu->addAction( ignoreForSession );
73 connect( ignoreTemporarily, &QAction::triggered,
this, [ = ]
75 mIgnoreMode = IgnoreTemporarily;
76 mIgnoreButton->setText( ignoreTemporarily->text() );
77 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
79 connect( ignoreForSession, &QAction::triggered,
this, [ = ]
81 mIgnoreMode = IgnoreForSession;
82 mIgnoreButton->setText( ignoreForSession->text() );
83 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
85 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
86 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
87 mIgnoreButton->setMenu( menu );
88 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
91 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
92 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
95 connect( mIgnoreButton, &QPushButton::clicked,
this, [ = ](
bool )
97 const QString realm { mRealm };
99 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
101 sIgnoredConnectionsCache->insert( realm );
103 if ( mIgnoreMode == IgnoreTemporarily )
105 QTimer::singleShot( 10000,
nullptr, [ = ]()
107 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
108 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
109 sIgnoredConnectionsCache->remove( realm );
115 leMasterPass->setPlaceholderText( tr(
"Required" ) );
116 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
118 leUsername->setFocus();
124 if ( qApp->thread() != QThread::currentThread() )
128 QgsDebugMsgLevel( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ), 2 );
132 requestCredentials( realm, &username, &password, message, &ok );
137void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
139 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
142 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
143 if ( sIgnoredConnectionsCache->contains( realm ) )
145 QgsDebugMsgLevel( QStringLiteral(
"Skipping ignored connection: " ) + realm, 2 );
150 stackedWidget->setCurrentIndex( 0 );
151 mIgnoreButton->show();
155 leUsername->setText( *username );
156 lePassword->setText( *password );
157 labelMessage->setText( message );
158 labelMessage->setHidden( message.isEmpty() );
160 if ( leUsername->text().isEmpty() )
161 leUsername->setFocus();
163 lePassword->setFocus();
165 QWidget *activeWindow = qApp->activeWindow();
167 QApplication::setOverrideCursor( Qt::ArrowCursor );
170 *ok = exec() == QDialog::Accepted;
171 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
173 QApplication::restoreOverrideCursor();
176 activeWindow->raise();
180 *username = leUsername->text();
181 *password = lePassword->text();
188 if ( qApp->thread() != QThread::currentThread() )
195 requestCredentialsMasterPassword( &password, stored, &ok );
200void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
203 stackedWidget->setCurrentIndex( 1 );
205 mIgnoreButton->hide();
206 leMasterPass->setFocus();
208 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
209 lblPasswordTitle->setText( titletxt );
213 leMasterPassVerify->setVisible( !stored );
214 lblDontForget->setVisible( !stored );
216 QApplication::setOverrideCursor( Qt::ArrowCursor );
218 grpbxPassAttempts->setVisible(
false );
222 mOkButton->setEnabled(
false );
224 if ( passfailed >= 3 )
226 lblSavedForSession->setVisible(
false );
227 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
228 grpbxPassAttempts->setVisible(
true );
232 QSize s = sizeHint();
233 s.setWidth( width() );
237 *ok = exec() == QDialog::Accepted;
238 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
242 bool passok = !leMasterPass->text().isEmpty();
243 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
248 if ( passok && !stored )
250 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
253 if ( passok || chkbxEraseAuthDb->isChecked() )
255 if ( stored && chkbxEraseAuthDb->isChecked() )
261 *password = leMasterPass->text();
275 leMasterPass->setStyleSheet( invalidStyle_() );
276 if ( leMasterPassVerify->isVisible() )
278 leMasterPassVerify->setStyleSheet( invalidStyle_() );
287 if ( passfailed >= 5 )
294 leMasterPass->clear();
295 leMasterPassVerify->clear();
297 chkbxEraseAuthDb->setChecked(
false );
298 lblSavedForSession->setVisible(
true );
302 mOkButton->setEnabled(
true );
304 QApplication::restoreOverrideCursor();
306 if ( passfailed >= 5 )
312void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
314 leMasterPass->setStyleSheet( QString() );
315 bool passok = !pass.isEmpty();
316 if ( leMasterPassVerify->isVisible() )
318 leMasterPassVerify->setStyleSheet( QString() );
319 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
321 mOkButton->setEnabled( passok );
323 if ( leMasterPassVerify->isVisible() && !passok )
325 leMasterPass->setStyleSheet( invalidStyle_() );
326 leMasterPassVerify->setStyleSheet( invalidStyle_() );
330void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
332 if ( leMasterPassVerify->isVisible() )
334 leMasterPass->setStyleSheet( QString() );
335 leMasterPassVerify->setStyleSheet( QString() );
338 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
339 mOkButton->setEnabled( passok );
342 leMasterPass->setStyleSheet( invalidStyle_() );
343 leMasterPassVerify->setStyleSheet( invalidStyle_() );
348void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
351 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.
static bool passwordHelperEnabled()
Password helper enabled getter.
void setPasswordHelperEnabled(bool enabled)
Password helper enabled setter.
void setScheduledAuthDatabaseErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
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, bool hide=false)
Removes the password element from a URI.
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)