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" ) );
112 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
114 leUsername->setFocus();
120 if ( qApp->thread() != QThread::currentThread() )
124 QgsDebugMsgLevel( u
"signal returned %1 (username=%2)"_s.arg( ok ?
"true" :
"false", username ), 2 );
128 requestCredentials( realm, &username, &password, message, &ok );
133void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
135 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
138 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
139 if ( sIgnoredConnectionsCache->contains( realm ) )
146 stackedWidget->setCurrentIndex( 0 );
147 mIgnoreButton->show();
151 leUsername->setText( *username );
152 lePassword->setText( *password );
153 labelMessage->setText( message );
154 labelMessage->setHidden( message.isEmpty() );
156 if ( leUsername->text().isEmpty() )
157 leUsername->setFocus();
159 lePassword->setFocus();
161 QWidget *activeWindow = qApp->activeWindow();
163 QApplication::setOverrideCursor( Qt::ArrowCursor );
166 *ok = exec() == QDialog::Accepted;
169 QApplication::restoreOverrideCursor();
172 activeWindow->raise();
176 *username = leUsername->text();
177 *password = lePassword->text();
184 if ( qApp->thread() != QThread::currentThread() )
191 requestCredentialsMasterPassword( &password, stored, &ok );
196void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
199 stackedWidget->setCurrentIndex( 1 );
201 mIgnoreButton->hide();
202 leMasterPass->setFocus();
204 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
205 lblPasswordTitle->setText( titletxt );
209 leMasterPassVerify->setVisible( !stored );
210 lblDontForget->setVisible( !stored );
212 QApplication::setOverrideCursor( Qt::ArrowCursor );
214 grpbxPassAttempts->setVisible(
false );
218 mOkButton->setEnabled(
false );
220 if ( passfailed >= 3 )
222 lblSavedForSession->setVisible(
false );
223 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
224 grpbxPassAttempts->setVisible(
true );
228 QSize s = sizeHint();
229 s.setWidth( width() );
233 *ok = exec() == QDialog::Accepted;
238 bool passok = !leMasterPass->text().isEmpty();
239 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
244 if ( passok && !stored )
246 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
249 if ( passok || chkbxEraseAuthDb->isChecked() )
251 if ( stored && chkbxEraseAuthDb->isChecked() )
257 *password = leMasterPass->text();
271 leMasterPass->setStyleSheet( invalidStyle_() );
272 if ( leMasterPassVerify->isVisible() )
274 leMasterPassVerify->setStyleSheet( invalidStyle_() );
283 if ( passfailed >= 5 )
290 leMasterPass->clear();
291 leMasterPassVerify->clear();
293 chkbxEraseAuthDb->setChecked(
false );
294 lblSavedForSession->setVisible(
true );
298 mOkButton->setEnabled(
true );
300 QApplication::restoreOverrideCursor();
302 if ( passfailed >= 5 )
308void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
310 leMasterPass->setStyleSheet( QString() );
311 bool passok = !pass.isEmpty();
312 if ( leMasterPassVerify->isVisible() )
314 leMasterPassVerify->setStyleSheet( QString() );
315 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
317 mOkButton->setEnabled( passok );
319 if ( leMasterPassVerify->isVisible() && !passok )
321 leMasterPass->setStyleSheet( invalidStyle_() );
322 leMasterPassVerify->setStyleSheet( invalidStyle_() );
326void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
328 if ( leMasterPassVerify->isVisible() )
330 leMasterPass->setStyleSheet( QString() );
331 leMasterPassVerify->setStyleSheet( QString() );
334 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
335 mOkButton->setEnabled( passok );
338 leMasterPass->setStyleSheet( invalidStyle_() );
339 leMasterPassVerify->setStyleSheet( invalidStyle_() );
344void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
347 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)