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 );
61 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
62 QMenu *menu =
new QMenu( mIgnoreButton );
63 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
64 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
65 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
66 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
67 menu->addAction( ignoreTemporarily );
68 menu->addAction( ignoreForSession );
69 connect( ignoreTemporarily, &QAction::triggered,
this, [=] {
70 mIgnoreMode = IgnoreTemporarily;
71 mIgnoreButton->setText( ignoreTemporarily->text() );
72 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
74 connect( ignoreForSession, &QAction::triggered,
this, [=] {
75 mIgnoreMode = IgnoreForSession;
76 mIgnoreButton->setText( ignoreForSession->text() );
77 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
79 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
80 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
81 mIgnoreButton->setMenu( menu );
82 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
85 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
86 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
89 connect( mIgnoreButton, &QPushButton::clicked,
this, [=](
bool ) {
90 const QString realm { mRealm };
92 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
94 sIgnoredConnectionsCache->insert( realm );
96 if ( mIgnoreMode == IgnoreTemporarily )
98 QTimer::singleShot( 10000,
nullptr, [=]() {
99 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
100 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
101 sIgnoredConnectionsCache->remove( realm );
107 leMasterPass->setPlaceholderText( tr(
"Required" ) );
108 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
110 leUsername->setFocus();
116 if ( qApp->thread() != QThread::currentThread() )
120 QgsDebugMsgLevel( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ), 2 );
124 requestCredentials( realm, &username, &password, message, &ok );
129void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
131 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
134 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
135 if ( sIgnoredConnectionsCache->contains( realm ) )
137 QgsDebugMsgLevel( QStringLiteral(
"Skipping ignored connection: " ) + realm, 2 );
142 stackedWidget->setCurrentIndex( 0 );
143 mIgnoreButton->show();
147 leUsername->setText( *username );
148 lePassword->setText( *password );
149 labelMessage->setText( message );
150 labelMessage->setHidden( message.isEmpty() );
152 if ( leUsername->text().isEmpty() )
153 leUsername->setFocus();
155 lePassword->setFocus();
157 QWidget *activeWindow = qApp->activeWindow();
159 QApplication::setOverrideCursor( Qt::ArrowCursor );
162 *ok = exec() == QDialog::Accepted;
163 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
165 QApplication::restoreOverrideCursor();
168 activeWindow->raise();
172 *username = leUsername->text();
173 *password = lePassword->text();
180 if ( qApp->thread() != QThread::currentThread() )
187 requestCredentialsMasterPassword( &password, stored, &ok );
192void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
195 stackedWidget->setCurrentIndex( 1 );
197 mIgnoreButton->hide();
198 leMasterPass->setFocus();
200 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
201 lblPasswordTitle->setText( titletxt );
205 leMasterPassVerify->setVisible( !stored );
206 lblDontForget->setVisible( !stored );
208 QApplication::setOverrideCursor( Qt::ArrowCursor );
210 grpbxPassAttempts->setVisible(
false );
214 mOkButton->setEnabled(
false );
216 if ( passfailed >= 3 )
218 lblSavedForSession->setVisible(
false );
219 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
220 grpbxPassAttempts->setVisible(
true );
224 QSize s = sizeHint();
225 s.setWidth( width() );
229 *ok = exec() == QDialog::Accepted;
230 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
234 bool passok = !leMasterPass->text().isEmpty();
235 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
240 if ( passok && !stored )
242 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
245 if ( passok || chkbxEraseAuthDb->isChecked() )
247 if ( stored && chkbxEraseAuthDb->isChecked() )
253 *password = leMasterPass->text();
267 leMasterPass->setStyleSheet( invalidStyle_() );
268 if ( leMasterPassVerify->isVisible() )
270 leMasterPassVerify->setStyleSheet( invalidStyle_() );
279 if ( passfailed >= 5 )
286 leMasterPass->clear();
287 leMasterPassVerify->clear();
289 chkbxEraseAuthDb->setChecked(
false );
290 lblSavedForSession->setVisible(
true );
294 mOkButton->setEnabled(
true );
296 QApplication::restoreOverrideCursor();
298 if ( passfailed >= 5 )
304void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
306 leMasterPass->setStyleSheet( QString() );
307 bool passok = !pass.isEmpty();
308 if ( leMasterPassVerify->isVisible() )
310 leMasterPassVerify->setStyleSheet( QString() );
311 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
313 mOkButton->setEnabled( passok );
315 if ( leMasterPassVerify->isVisible() && !passok )
317 leMasterPass->setStyleSheet( invalidStyle_() );
318 leMasterPassVerify->setStyleSheet( invalidStyle_() );
322void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
324 if ( leMasterPassVerify->isVisible() )
326 leMasterPass->setStyleSheet( QString() );
327 leMasterPassVerify->setStyleSheet( QString() );
330 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
331 mOkButton->setEnabled( passok );
334 leMasterPass->setStyleSheet( invalidStyle_() );
335 leMasterPassVerify->setStyleSheet( invalidStyle_() );
340void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
343 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)