File indexing completed on 2025-02-16 04:50:21

0001 /*
0002     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003     SPDX-FileContributor: Kevin Ottens <kevin@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "settingspasswordrequester.h"
0009 
0010 #include <KLocalizedString>
0011 #include <KMessageBox>
0012 
0013 #include "imapresource_debug.h"
0014 #include "imapresourcebase.h"
0015 #include "settings.h"
0016 #include <KAuthorized>
0017 #include <KPasswordDialog>
0018 #include <QDialogButtonBox>
0019 #include <QPushButton>
0020 #include <kwindowsystem.h>
0021 #include <mailtransport/transportbase.h>
0022 
0023 SettingsPasswordRequester::SettingsPasswordRequester(ImapResourceBase *resource, QObject *parent)
0024     : PasswordRequesterInterface(parent)
0025     , m_resource(resource)
0026 {
0027 }
0028 
0029 SettingsPasswordRequester::~SettingsPasswordRequester()
0030 {
0031     cancelPasswordRequests();
0032 }
0033 
0034 void SettingsPasswordRequester::requestPassword(RequestType request, const QString &serverError)
0035 {
0036     if (request == WrongPasswordRequest) {
0037         QMetaObject::invokeMethod(this, "askUserInput", Qt::QueuedConnection, Q_ARG(QString, serverError));
0038     } else {
0039         connect(m_resource->settings(), &Settings::passwordRequestCompleted, this, &SettingsPasswordRequester::onPasswordRequestCompleted);
0040         m_resource->settings()->requestPassword();
0041     }
0042 }
0043 
0044 void SettingsPasswordRequester::askUserInput(const QString &serverError)
0045 {
0046     // the credentials were not ok, allow to retry or change password
0047     if (m_requestDialog) {
0048         qCDebug(IMAPRESOURCE_LOG) << "Password request dialog is already open";
0049         return;
0050     }
0051     QWidget *parent = QWidget::find(m_resource->winIdForDialogs());
0052     const QString text = i18n(
0053         "The server for account \"%2\" refused the supplied username and password.\n"
0054         "Do you want to go to the settings, have another attempt "
0055         "at logging in, or do nothing?\n\n"
0056         "%1",
0057         serverError,
0058         m_resource->name());
0059     auto dialog = new QDialog(parent, Qt::Dialog);
0060     dialog->setWindowTitle(i18nc("@title:window", "Could Not Authenticate"));
0061     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::No | QDialogButtonBox::Yes, dialog);
0062     buttonBox->button(QDialogButtonBox::Yes)->setDefault(true);
0063 
0064     buttonBox->button(QDialogButtonBox::Yes)->setText(i18n("Account Settings"));
0065     buttonBox->button(QDialogButtonBox::No)->setText(i18nc("Input username/password manually and not store them", "Try Again"));
0066     dialog->setAttribute(Qt::WA_DeleteOnClose);
0067     connect(buttonBox->button(QDialogButtonBox::Yes), &QPushButton::clicked, this, &SettingsPasswordRequester::slotYesClicked);
0068     connect(buttonBox->button(QDialogButtonBox::No), &QPushButton::clicked, this, &SettingsPasswordRequester::slotNoClicked);
0069     connect(buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &SettingsPasswordRequester::slotCancelClicked);
0070 
0071     connect(dialog, &QDialog::destroyed, this, &SettingsPasswordRequester::onDialogDestroyed);
0072     m_requestDialog = dialog;
0073     dialog->setAttribute(Qt::WA_NativeWindow, true);
0074     KWindowSystem::setMainWindow(dialog->windowHandle(), m_resource->winIdForDialogs());
0075     bool checkboxResult = false;
0076     KMessageBox::createKMessageBox(dialog, buttonBox, QMessageBox::Information, text, QStringList(), QString(), &checkboxResult, KMessageBox::NoExec);
0077     dialog->show();
0078 }
0079 
0080 void SettingsPasswordRequester::onDialogDestroyed()
0081 {
0082     m_requestDialog = nullptr;
0083 }
0084 
0085 void SettingsPasswordRequester::slotNoClicked()
0086 {
0087     connect(m_resource->settings(), &Settings::passwordRequestCompleted, this, &SettingsPasswordRequester::onPasswordRequestCompleted);
0088     requestManualAuth(nullptr);
0089     m_requestDialog = nullptr;
0090 }
0091 
0092 void SettingsPasswordRequester::slotYesClicked()
0093 {
0094     if (!m_settingsDialog) {
0095         QDialog *dialog = m_resource->createConfigureDialog(m_resource->winIdForDialogs());
0096         connect(dialog, &QDialog::finished, this, &SettingsPasswordRequester::onSettingsDialogFinished);
0097         m_settingsDialog = dialog;
0098         dialog->show();
0099     }
0100     m_requestDialog = nullptr;
0101 }
0102 
0103 void SettingsPasswordRequester::slotCancelClicked()
0104 {
0105     Q_EMIT done(UserRejected);
0106     m_requestDialog = nullptr;
0107 }
0108 
0109 void SettingsPasswordRequester::onSettingsDialogFinished(int result)
0110 {
0111     m_settingsDialog = nullptr;
0112     if (result == QDialog::Accepted) {
0113         Q_EMIT done(ReconnectNeeded);
0114     } else {
0115         Q_EMIT done(UserRejected);
0116     }
0117 }
0118 
0119 void SettingsPasswordRequester::cancelPasswordRequests()
0120 {
0121     if (m_requestDialog) {
0122         if (m_requestDialog->close()) {
0123             m_requestDialog = nullptr;
0124         }
0125     }
0126 }
0127 
0128 void SettingsPasswordRequester::onPasswordRequestCompleted(const QString &password, bool userRejected)
0129 {
0130     disconnect(m_resource->settings(), &Settings::passwordRequestCompleted, this, &SettingsPasswordRequester::onPasswordRequestCompleted);
0131 
0132     QString pwd = password;
0133     if (userRejected || pwd.isEmpty()) {
0134         pwd = requestManualAuth(&userRejected);
0135     }
0136 
0137     if (userRejected) {
0138         Q_EMIT done(UserRejected);
0139     } else if (password.isEmpty() && (m_resource->settings()->authentication() != MailTransport::Transport::EnumAuthenticationType::GSSAPI)) {
0140         Q_EMIT done(EmptyPasswordEntered);
0141     } else {
0142         Q_EMIT done(PasswordRetrieved, password);
0143     }
0144 }
0145 
0146 QString SettingsPasswordRequester::requestManualAuth(bool *userRejected)
0147 {
0148     QScopedPointer<KPasswordDialog> dlg(new KPasswordDialog(nullptr));
0149     dlg->setModal(true);
0150     dlg->setPrompt(i18n("Please enter password for user '%1' on IMAP server '%2'.", m_resource->settings()->userName(), m_resource->settings()->imapServer()));
0151     dlg->setPassword(m_resource->settings()->password());
0152     dlg->setRevealPasswordAvailable(KAuthorized::authorize(QStringLiteral("lineedit_reveal_password")));
0153     if (dlg->exec()) {
0154         if (userRejected) {
0155             *userRejected = false;
0156         }
0157         m_resource->settings()->setPassword(dlg->password());
0158         return dlg->password();
0159     } else {
0160         if (userRejected) {
0161             *userRejected = true;
0162         }
0163         return {};
0164     }
0165 }
0166 
0167 #include "moc_settingspasswordrequester.cpp"