26#include <QGlobalStatic>
34#include "moc_qgscredentialdialog.cpp"
36using namespace Qt::StringLiterals;
38QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
45static QString invalidStyle_(
const QString &selector = u
"QLineEdit"_s )
47 return u
"%1{color: rgb(200, 0, 0);}"_s.arg( selector );
51 : QDialog( parent, fl )
57 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
58 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
59 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
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, [
this, ignoreTemporarily] {
74 mIgnoreMode = IgnoreTemporarily;
75 mIgnoreButton->setText( ignoreTemporarily->text() );
76 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
78 connect( ignoreForSession, &QAction::triggered,
this, [
this, ignoreForSession] {
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, [
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, [realm]() {
103 QgsDebugMsgLevel( u
"Removing ignored connection from cache: %1"_s.arg( realm ), 4 );
104 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
105 sIgnoredConnectionsCache->remove( realm );
111 leMasterPass->setPlaceholderText( tr(
"Required" ) );
113 leUsername->setFocus();
119 if ( qApp->thread() != QThread::currentThread() )
123 QgsDebugMsgLevel( u
"signal returned %1 (username=%2)"_s.arg( ok ?
"true" :
"false", username ), 2 );
127 requestCredentials( realm, &username, &password, message, &ok );
132void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
134 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
137 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
138 if ( sIgnoredConnectionsCache->contains( realm ) )
145 stackedWidget->setCurrentIndex( 0 );
146 mIgnoreButton->show();
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;
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 );
195void 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;
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 )
307void 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_() );
325void 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_() );
343void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
346 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 QString passwordHelperDisplayName(bool titleCase=false)
Returns a translated 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)