22 #include "qgssettings.h" 
   25 #include <QPushButton> 
   27 #include <QToolButton> 
   30 #include <QGlobalStatic> 
   32 QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
 
   39 static QString invalidStyle_( 
const QString &selector = QStringLiteral( 
"QLineEdit" ) )
 
   41   return QStringLiteral( 
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
 
   45   : QDialog( parent, fl )
 
   49   connect( leMasterPass, &QgsPasswordLineEdit::textChanged, 
this, &QgsCredentialDialog::leMasterPass_textChanged );
 
   50   connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged, 
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
 
   51   connect( chkbxEraseAuthDb, &QCheckBox::toggled, 
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
 
   54            this, &QgsCredentialDialog::requestCredentials,
 
   55            Qt::BlockingQueuedConnection );
 
   57            this, &QgsCredentialDialog::requestCredentialsMasterPassword,
 
   58            Qt::BlockingQueuedConnection );
 
   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, [ = ]
 
   71     mIgnoreMode = IgnoreTemporarily;
 
   72     mIgnoreButton->setText( ignoreTemporarily->text() );
 
   73     mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
 
   75   connect( ignoreForSession, &QAction::triggered, 
this, [ = ]
 
   77     mIgnoreMode = IgnoreForSession;
 
   78     mIgnoreButton->setText( ignoreForSession->text() );
 
   79     mIgnoreButton->setToolTip( ignoreForSession->toolTip() );
 
   81   mIgnoreButton->setText( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->text() : ignoreForSession->text() );
 
   82   mIgnoreButton->setToolTip( mIgnoreMode == IgnoreTemporarily ? ignoreTemporarily->toolTip() : ignoreForSession->toolTip() );
 
   83   mIgnoreButton->setMenu( menu );
 
   84   mIgnoreButton->setMaximumHeight( mOkButton->sizeHint().height() );
 
   87   connect( mOkButton, &QPushButton::clicked, 
this, &QgsCredentialDialog::accept );
 
   88   connect( mCancelButton, &QPushButton::clicked, 
this, &QgsCredentialDialog::reject );
 
   91   connect( mIgnoreButton, &QPushButton::clicked, 
this, [ = ]( 
bool )
 
   93     const QString realm { labelRealm->text() };
 
   95       QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
 
   97       sIgnoredConnectionsCache->insert( realm );
 
   99     if ( mIgnoreMode == IgnoreTemporarily )
 
  101       QTimer::singleShot( 10000, 
nullptr, [ = ]()
 
  103         QgsDebugMsgLevel( QStringLiteral( 
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
 
  104         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() )
 
  122     QgsDebugMsg( QStringLiteral( 
"emitting signal" ) );
 
  124     QgsDebugMsg( QStringLiteral( 
"signal returned %1 (username=%2)" ).arg( ok ? 
"true" : 
"false", username ) );
 
  128     requestCredentials( realm, &username, &password, message, &ok );
 
  133 void QgsCredentialDialog::requestCredentials( 
const QString &realm, QString *username, QString *password, 
const QString &message, 
bool *ok )
 
  135   Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
 
  138     QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
 
  139     if ( sIgnoredConnectionsCache->contains( realm ) )
 
  141       QgsDebugMsg( QStringLiteral( 
"Skipping ignored connection: " ) + realm );
 
  146   stackedWidget->setCurrentIndex( 0 );
 
  147   mIgnoreButton->show();
 
  149   labelRealm->setText( realm );
 
  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;
 
  166   QgsDebugMsgLevel( QStringLiteral( 
"exec(): %1" ).arg( *ok ? 
"true" : 
"false" ), 4 );
 
  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 );
 
  195 void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password, 
bool stored, 
bool *ok )
 
  198   stackedWidget->setCurrentIndex( 1 );
 
  200   mIgnoreButton->hide();
 
  201   leMasterPass->setFocus();
 
  203   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;
 
  233     QgsDebugMsgLevel( QStringLiteral( 
"exec(): %1" ).arg( *ok ? 
"true" : 
"false" ), 4 );
 
  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 )
 
  307 void 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_() );
 
  325 void QgsCredentialDialog::leMasterPassVerify_textChanged( 
const QString &pass )
 
  327   if ( leMasterPassVerify->isVisible() )
 
  329     leMasterPass->setStyleSheet( QString() );
 
  330     leMasterPassVerify->setStyleSheet( QString() );
 
  333     bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
 
  334     mOkButton->setEnabled( passok );
 
  337       leMasterPass->setStyleSheet( invalidStyle_() );
 
  338       leMasterPassVerify->setStyleSheet( invalidStyle_() );
 
  343 void 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.
void setPasswordHelperEnabled(bool enabled)
Password helper enabled setter.
void setScheduledAuthDatabaseErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
bool passwordHelperEnabled() const
Password helper enabled getter.
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
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)