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 )
52 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
53 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
54 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
57 this, &QgsCredentialDialog::requestCredentials,
58 Qt::BlockingQueuedConnection );
60 this, &QgsCredentialDialog::requestCredentialsMasterPassword,
61 Qt::BlockingQueuedConnection );
64 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
65 QMenu *menu =
new QMenu( mIgnoreButton );
66 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
67 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
68 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
69 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
70 menu->addAction( ignoreTemporarily );
71 menu->addAction( ignoreForSession );
72 connect( ignoreTemporarily, &QAction::triggered,
this, [ = ]
74 mIgnoreMode = IgnoreTemporarily;
75 mIgnoreButton->setText( ignoreTemporarily->text() );
76 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
78 connect( ignoreForSession, &QAction::triggered,
this, [ = ]
80 mIgnoreMode = IgnoreForSession;
81 mIgnoreButton->setText( ignoreForSession->text() );
82 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
84 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
85 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
86 mIgnoreButton->setMenu( menu );
87 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
90 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
91 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
94 connect( mIgnoreButton, &QPushButton::clicked,
this, [ = ](
bool )
96 const QString realm { mRealm };
98 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
100 sIgnoredConnectionsCache->insert( realm );
102 if ( mIgnoreMode == IgnoreTemporarily )
104 QTimer::singleShot( 10000,
nullptr, [ = ]()
106 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
107 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
108 sIgnoredConnectionsCache->remove( realm );
114 leMasterPass->setPlaceholderText( tr(
"Required" ) );
115 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
117 leUsername->setFocus();
123 if ( qApp->thread() != QThread::currentThread() )
127 QgsDebugMsgLevel( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ), 2 );
131 requestCredentials( realm, &username, &password, message, &ok );
136void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
138 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
141 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
142 if ( sIgnoredConnectionsCache->contains( realm ) )
144 QgsDebugMsgLevel( QStringLiteral(
"Skipping ignored connection: " ) + realm, 2 );
149 stackedWidget->setCurrentIndex( 0 );
150 mIgnoreButton->show();
154 leUsername->setText( *username );
155 lePassword->setText( *password );
156 labelMessage->setText( message );
157 labelMessage->setHidden( message.isEmpty() );
159 if ( leUsername->text().isEmpty() )
160 leUsername->setFocus();
162 lePassword->setFocus();
164 QWidget *activeWindow = qApp->activeWindow();
166 QApplication::setOverrideCursor( Qt::ArrowCursor );
169 *ok = exec() == QDialog::Accepted;
170 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
172 QApplication::restoreOverrideCursor();
175 activeWindow->raise();
179 *username = leUsername->text();
180 *password = lePassword->text();
187 if ( qApp->thread() != QThread::currentThread() )
194 requestCredentialsMasterPassword( &password, stored, &ok );
199void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
202 stackedWidget->setCurrentIndex( 1 );
204 mIgnoreButton->hide();
205 leMasterPass->setFocus();
207 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
208 lblPasswordTitle->setText( titletxt );
212 leMasterPassVerify->setVisible( !stored );
213 lblDontForget->setVisible( !stored );
215 QApplication::setOverrideCursor( Qt::ArrowCursor );
217 grpbxPassAttempts->setVisible(
false );
221 mOkButton->setEnabled(
false );
223 if ( passfailed >= 3 )
225 lblSavedForSession->setVisible(
false );
226 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
227 grpbxPassAttempts->setVisible(
true );
231 QSize s = sizeHint();
232 s.setWidth( width() );
236 *ok = exec() == QDialog::Accepted;
237 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
241 bool passok = !leMasterPass->text().isEmpty();
242 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
247 if ( passok && !stored )
249 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
252 if ( passok || chkbxEraseAuthDb->isChecked() )
254 if ( stored && chkbxEraseAuthDb->isChecked() )
260 *password = leMasterPass->text();
274 leMasterPass->setStyleSheet( invalidStyle_() );
275 if ( leMasterPassVerify->isVisible() )
277 leMasterPassVerify->setStyleSheet( invalidStyle_() );
286 if ( passfailed >= 5 )
293 leMasterPass->clear();
294 leMasterPassVerify->clear();
296 chkbxEraseAuthDb->setChecked(
false );
297 lblSavedForSession->setVisible(
true );
301 mOkButton->setEnabled(
true );
303 QApplication::restoreOverrideCursor();
305 if ( passfailed >= 5 )
311void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
313 leMasterPass->setStyleSheet( QString() );
314 bool passok = !pass.isEmpty();
315 if ( leMasterPassVerify->isVisible() )
317 leMasterPassVerify->setStyleSheet( QString() );
318 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
320 mOkButton->setEnabled( passok );
322 if ( leMasterPassVerify->isVisible() && !passok )
324 leMasterPass->setStyleSheet( invalidStyle_() );
325 leMasterPassVerify->setStyleSheet( invalidStyle_() );
329void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
331 if ( leMasterPassVerify->isVisible() )
333 leMasterPass->setStyleSheet( QString() );
334 leMasterPassVerify->setStyleSheet( QString() );
337 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
338 mOkButton->setEnabled( passok );
341 leMasterPass->setStyleSheet( invalidStyle_() );
342 leMasterPassVerify->setStyleSheet( invalidStyle_() );
347void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
350 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)