26#include <QGlobalStatic>
33#include "moc_qgscredentialdialog.cpp"
35QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
42static QString invalidStyle_(
const QString &selector = QStringLiteral(
"QLineEdit" ) )
44 return QStringLiteral(
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
48 : QDialog( parent, fl )
54 connect( leMasterPass, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPass_textChanged );
55 connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged,
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
56 connect( chkbxEraseAuthDb, &QCheckBox::toggled,
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
62 mIgnoreButton->setToolTip( tr(
"All requests for this connection will be automatically rejected" ) );
63 QMenu *menu =
new QMenu( mIgnoreButton );
64 QAction *ignoreTemporarily =
new QAction( tr(
"Ignore for 10 Seconds" ), menu );
65 ignoreTemporarily->setToolTip( tr(
"All requests for this connection will be automatically rejected for 10 seconds" ) );
66 QAction *ignoreForSession =
new QAction( tr(
"Ignore for Session" ), menu );
67 ignoreForSession->setToolTip( tr(
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
68 menu->addAction( ignoreTemporarily );
69 menu->addAction( ignoreForSession );
70 connect( ignoreTemporarily, &QAction::triggered,
this, [
this, ignoreTemporarily] {
71 mIgnoreMode = IgnoreTemporarily;
72 mIgnoreButton->setText( ignoreTemporarily->text() );
73 mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
75 connect( ignoreForSession, &QAction::triggered,
this, [
this, ignoreForSession] {
76 mIgnoreMode = IgnoreForSession;
77 mIgnoreButton->setText( ignoreForSession->text() );
78 mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
80 mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
81 mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
82 mIgnoreButton->setMenu( menu );
83 mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
86 connect( mOkButton, &QPushButton::clicked,
this, &QgsCredentialDialog::accept );
87 connect( mCancelButton, &QPushButton::clicked,
this, &QgsCredentialDialog::reject );
90 connect( mIgnoreButton, &QPushButton::clicked,
this, [
this](
bool ) {
91 const QString realm { mRealm };
93 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
95 sIgnoredConnectionsCache->insert( realm );
97 if ( mIgnoreMode == IgnoreTemporarily )
99 QTimer::singleShot( 10000,
nullptr, [realm]() {
100 QgsDebugMsgLevel( QStringLiteral(
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
101 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
102 sIgnoredConnectionsCache->remove( realm );
108 leMasterPass->setPlaceholderText( tr(
"Required" ) );
109 chkbxPasswordHelperEnable->setText( tr(
"Store/update the master password in your %1" )
111 leUsername->setFocus();
117 if ( qApp->thread() != QThread::currentThread() )
121 QgsDebugMsgLevel( QStringLiteral(
"signal returned %1 (username=%2)" ).arg( ok ?
"true" :
"false", username ), 2 );
125 requestCredentials( realm, &username, &password, message, &ok );
130void QgsCredentialDialog::requestCredentials(
const QString &realm, QString *username, QString *password,
const QString &message,
bool *ok )
132 Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
135 const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
136 if ( sIgnoredConnectionsCache->contains( realm ) )
138 QgsDebugMsgLevel( QStringLiteral(
"Skipping ignored connection: " ) + realm, 2 );
143 stackedWidget->setCurrentIndex( 0 );
144 mIgnoreButton->show();
148 leUsername->setText( *username );
149 lePassword->setText( *password );
150 labelMessage->setText( message );
151 labelMessage->setHidden( message.isEmpty() );
153 if ( leUsername->text().isEmpty() )
154 leUsername->setFocus();
156 lePassword->setFocus();
158 QWidget *activeWindow = qApp->activeWindow();
160 QApplication::setOverrideCursor( Qt::ArrowCursor );
163 *ok = exec() == QDialog::Accepted;
164 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
166 QApplication::restoreOverrideCursor();
169 activeWindow->raise();
173 *username = leUsername->text();
174 *password = lePassword->text();
181 if ( qApp->thread() != QThread::currentThread() )
188 requestCredentialsMasterPassword( &password, stored, &ok );
193void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password,
bool stored,
bool *ok )
196 stackedWidget->setCurrentIndex( 1 );
198 mIgnoreButton->hide();
199 leMasterPass->setFocus();
201 const QString titletxt( stored ? tr(
"Enter CURRENT master authentication password" ) : tr(
"Set NEW master authentication password" ) );
202 lblPasswordTitle->setText( titletxt );
206 leMasterPassVerify->setVisible( !stored );
207 lblDontForget->setVisible( !stored );
209 QApplication::setOverrideCursor( Qt::ArrowCursor );
211 grpbxPassAttempts->setVisible(
false );
215 mOkButton->setEnabled(
false );
217 if ( passfailed >= 3 )
219 lblSavedForSession->setVisible(
false );
220 grpbxPassAttempts->setTitle( tr(
"Password attempts: %1" ).arg( passfailed ) );
221 grpbxPassAttempts->setVisible(
true );
225 QSize s = sizeHint();
226 s.setWidth( width() );
230 *ok = exec() == QDialog::Accepted;
231 QgsDebugMsgLevel( QStringLiteral(
"exec(): %1" ).arg( *ok ?
"true" :
"false" ), 4 );
235 bool passok = !leMasterPass->text().isEmpty();
236 if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
241 if ( passok && !stored )
243 passok = ( leMasterPass->text() == leMasterPassVerify->text() );
246 if ( passok || chkbxEraseAuthDb->isChecked() )
248 if ( stored && chkbxEraseAuthDb->isChecked() )
254 *password = leMasterPass->text();
268 leMasterPass->setStyleSheet( invalidStyle_() );
269 if ( leMasterPassVerify->isVisible() )
271 leMasterPassVerify->setStyleSheet( invalidStyle_() );
280 if ( passfailed >= 5 )
287 leMasterPass->clear();
288 leMasterPassVerify->clear();
290 chkbxEraseAuthDb->setChecked(
false );
291 lblSavedForSession->setVisible(
true );
295 mOkButton->setEnabled(
true );
297 QApplication::restoreOverrideCursor();
299 if ( passfailed >= 5 )
305void QgsCredentialDialog::leMasterPass_textChanged(
const QString &pass )
307 leMasterPass->setStyleSheet( QString() );
308 bool passok = !pass.isEmpty();
309 if ( leMasterPassVerify->isVisible() )
311 leMasterPassVerify->setStyleSheet( QString() );
312 passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
314 mOkButton->setEnabled( passok );
316 if ( leMasterPassVerify->isVisible() && !passok )
318 leMasterPass->setStyleSheet( invalidStyle_() );
319 leMasterPassVerify->setStyleSheet( invalidStyle_() );
323void QgsCredentialDialog::leMasterPassVerify_textChanged(
const QString &pass )
325 if ( leMasterPassVerify->isVisible() )
327 leMasterPass->setStyleSheet( QString() );
328 leMasterPassVerify->setStyleSheet( QString() );
331 const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
332 mOkButton->setEnabled( passok );
335 leMasterPass->setStyleSheet( invalidStyle_() );
336 leMasterPassVerify->setStyleSheet( invalidStyle_() );
341void QgsCredentialDialog::chkbxEraseAuthDb_toggled(
bool checked )
344 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)