30#include <QGlobalStatic> 
   32QMutex QgsCredentialDialog::sIgnoredConnectionsCacheMutex;
 
   39static QString invalidStyle_( 
const QString &selector = QStringLiteral( 
"QLineEdit" ) )
 
   41  return QStringLiteral( 
"%1{color: rgb(200, 0, 0);}" ).arg( selector );
 
   45  : QDialog( parent, fl )
 
   51  connect( leMasterPass, &QgsPasswordLineEdit::textChanged, 
this, &QgsCredentialDialog::leMasterPass_textChanged );
 
   52  connect( leMasterPassVerify, &QgsPasswordLineEdit::textChanged, 
this, &QgsCredentialDialog::leMasterPassVerify_textChanged );
 
   53  connect( chkbxEraseAuthDb, &QCheckBox::toggled, 
this, &QgsCredentialDialog::chkbxEraseAuthDb_toggled );
 
   56           this, &QgsCredentialDialog::requestCredentials,
 
   57           Qt::BlockingQueuedConnection );
 
   59           this, &QgsCredentialDialog::requestCredentialsMasterPassword,
 
   60           Qt::BlockingQueuedConnection );
 
   63  mIgnoreButton->setToolTip( tr( 
"All requests for this connection will be automatically rejected" ) );
 
   64  QMenu *menu = 
new QMenu( mIgnoreButton );
 
   65  QAction *ignoreTemporarily = 
new QAction( tr( 
"Ignore for 10 Seconds" ), menu );
 
   66  ignoreTemporarily->setToolTip( tr( 
"All requests for this connection will be automatically rejected for 10 seconds" ) );
 
   67  QAction *ignoreForSession = 
new QAction( tr( 
"Ignore for Session" ), menu );
 
   68  ignoreForSession->setToolTip( tr( 
"All requests for this connection will be automatically rejected for the duration of the current session" ) );
 
   69  menu->addAction( ignoreTemporarily );
 
   70  menu->addAction( ignoreForSession );
 
   71  connect( ignoreTemporarily, &QAction::triggered, 
this, [ = ]
 
   73    mIgnoreMode = IgnoreTemporarily;
 
   74    mIgnoreButton->setText( ignoreTemporarily->text() );
 
   75    mIgnoreButton->setToolTip( ignoreTemporarily->toolTip() );
 
   77  connect( ignoreForSession, &QAction::triggered, 
this, [ = ]
 
   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, [ = ]( 
bool )
 
   95    const QString realm { labelRealm->text() };
 
   97      const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
 
   99      sIgnoredConnectionsCache->insert( realm );
 
  101    if ( mIgnoreMode == IgnoreTemporarily )
 
  103      QTimer::singleShot( 10000, 
nullptr, [ = ]()
 
  105        QgsDebugMsgLevel( QStringLiteral( 
"Removing ignored connection from cache: %1" ).arg( realm ), 4 );
 
  106        const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
 
  107        sIgnoredConnectionsCache->remove( realm );
 
  113  leMasterPass->setPlaceholderText( tr( 
"Required" ) );
 
  114  chkbxPasswordHelperEnable->setText( tr( 
"Store/update the master password in your %1" )
 
  116  leUsername->setFocus();
 
  122  if ( qApp->thread() != QThread::currentThread() )
 
  126    QgsDebugMsgLevel( QStringLiteral( 
"signal returned %1 (username=%2)" ).arg( ok ? 
"true" : 
"false", username ), 2 );
 
  130    requestCredentials( realm, &username, &password, message, &ok );
 
  135void QgsCredentialDialog::requestCredentials( 
const QString &realm, QString *username, QString *password, 
const QString &message, 
bool *ok )
 
  137  Q_ASSERT( qApp->thread() == thread() && thread() == QThread::currentThread() );
 
  140    const QMutexLocker locker( &sIgnoredConnectionsCacheMutex );
 
  141    if ( sIgnoredConnectionsCache->contains( realm ) )
 
  143      QgsDebugMsgLevel( QStringLiteral( 
"Skipping ignored connection: " ) + realm, 2 );
 
  148  stackedWidget->setCurrentIndex( 0 );
 
  149  mIgnoreButton->show();
 
  151  labelRealm->setText( realm );
 
  152  leUsername->setText( *username );
 
  153  lePassword->setText( *password );
 
  154  labelMessage->setText( message );
 
  155  labelMessage->setHidden( message.isEmpty() );
 
  157  if ( leUsername->text().isEmpty() )
 
  158    leUsername->setFocus();
 
  160    lePassword->setFocus();
 
  162  QWidget *activeWindow = qApp->activeWindow();
 
  164  QApplication::setOverrideCursor( Qt::ArrowCursor );
 
  167  *ok = exec() == QDialog::Accepted;
 
  168  QgsDebugMsgLevel( QStringLiteral( 
"exec(): %1" ).arg( *ok ? 
"true" : 
"false" ), 4 );
 
  170  QApplication::restoreOverrideCursor();
 
  173    activeWindow->raise();
 
  177    *username = leUsername->text();
 
  178    *password = lePassword->text();
 
  185  if ( qApp->thread() != QThread::currentThread() )
 
  192    requestCredentialsMasterPassword( &password, stored, &ok );
 
  197void QgsCredentialDialog::requestCredentialsMasterPassword( QString *password, 
bool stored, 
bool *ok )
 
  200  stackedWidget->setCurrentIndex( 1 );
 
  202  mIgnoreButton->hide();
 
  203  leMasterPass->setFocus();
 
  205  const QString titletxt( stored ? tr( 
"Enter CURRENT master authentication password" ) : tr( 
"Set NEW master authentication password" ) );
 
  206  lblPasswordTitle->setText( titletxt );
 
  210  leMasterPassVerify->setVisible( !stored );
 
  211  lblDontForget->setVisible( !stored );
 
  213  QApplication::setOverrideCursor( Qt::ArrowCursor );
 
  215  grpbxPassAttempts->setVisible( 
false );
 
  219    mOkButton->setEnabled( 
false );
 
  221    if ( passfailed >= 3 )
 
  223      lblSavedForSession->setVisible( 
false );
 
  224      grpbxPassAttempts->setTitle( tr( 
"Password attempts: %1" ).arg( passfailed ) );
 
  225      grpbxPassAttempts->setVisible( 
true );
 
  229    QSize s = sizeHint();
 
  230    s.setWidth( width() );
 
  234    *ok = exec() == QDialog::Accepted;
 
  235    QgsDebugMsgLevel( QStringLiteral( 
"exec(): %1" ).arg( *ok ? 
"true" : 
"false" ), 4 );
 
  239      bool passok = !leMasterPass->text().isEmpty();
 
  240      if ( passok && stored && !chkbxEraseAuthDb->isChecked() )
 
  245      if ( passok && !stored )
 
  247        passok = ( leMasterPass->text() == leMasterPassVerify->text() );
 
  250      if ( passok || chkbxEraseAuthDb->isChecked() )
 
  252        if ( stored && chkbxEraseAuthDb->isChecked() )
 
  258          *password = leMasterPass->text();
 
  272        leMasterPass->setStyleSheet( invalidStyle_() );
 
  273        if ( leMasterPassVerify->isVisible() )
 
  275          leMasterPassVerify->setStyleSheet( invalidStyle_() );
 
  284    if ( passfailed >= 5 )
 
  291  leMasterPass->clear();
 
  292  leMasterPassVerify->clear();
 
  294  chkbxEraseAuthDb->setChecked( 
false );
 
  295  lblSavedForSession->setVisible( 
true );
 
  299  mOkButton->setEnabled( 
true );
 
  301  QApplication::restoreOverrideCursor();
 
  303  if ( passfailed >= 5 )
 
  309void QgsCredentialDialog::leMasterPass_textChanged( 
const QString &pass )
 
  311  leMasterPass->setStyleSheet( QString() );
 
  312  bool passok = !pass.isEmpty(); 
 
  313  if ( leMasterPassVerify->isVisible() )
 
  315    leMasterPassVerify->setStyleSheet( QString() );
 
  316    passok = passok && ( leMasterPass->text() == leMasterPassVerify->text() );
 
  318  mOkButton->setEnabled( passok );
 
  320  if ( leMasterPassVerify->isVisible() && !passok )
 
  322    leMasterPass->setStyleSheet( invalidStyle_() );
 
  323    leMasterPassVerify->setStyleSheet( invalidStyle_() );
 
  327void QgsCredentialDialog::leMasterPassVerify_textChanged( 
const QString &pass )
 
  329  if ( leMasterPassVerify->isVisible() )
 
  331    leMasterPass->setStyleSheet( QString() );
 
  332    leMasterPassVerify->setStyleSheet( QString() );
 
  335    const bool passok = !pass.isEmpty() && ( leMasterPass->text() == leMasterPassVerify->text() );
 
  336    mOkButton->setEnabled( passok );
 
  339      leMasterPass->setStyleSheet( invalidStyle_() );
 
  340      leMasterPassVerify->setStyleSheet( invalidStyle_() );
 
  345void QgsCredentialDialog::chkbxEraseAuthDb_toggled( 
bool checked )
 
  348    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
 
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)