File indexing completed on 2024-12-01 07:42:31
0001 /* 0002 SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ruqolaloginwidget.h" 0008 #include "colorsandmessageviewstyle.h" 0009 #include "common/authenticationoauthwidget.h" 0010 #include "misc/passwordlineeditwidget.h" 0011 #include "misc/twoauthenticationpasswordwidget.h" 0012 #include "rocketchataccount.h" 0013 #include "ruqola_password_widgets_debug.h" 0014 #include <KBusyIndicatorWidget> 0015 #include <KColorScheme> 0016 #include <KLocalizedString> 0017 #include <KPasswordLineEdit> 0018 #include <QCheckBox> 0019 #include <QFormLayout> 0020 #include <QLabel> 0021 #include <QLineEdit> 0022 #include <QPushButton> 0023 #include <QVBoxLayout> 0024 0025 RuqolaLoginWidget::RuqolaLoginWidget(QWidget *parent) 0026 : QWidget(parent) 0027 , mAccountName(new QLineEdit(this)) 0028 , mServerUrl(new QLineEdit(this)) 0029 , mUserName(new QLineEdit(this)) 0030 , mPasswordLineEditWidget(new PasswordLineEditWidget(this)) 0031 , mLoginButton(new QPushButton(i18n("Login"), this)) 0032 , mBusyIndicatorWidget(new KBusyIndicatorWidget(this)) 0033 , mFailedError(new QLabel(this)) 0034 , mTwoFactorAuthenticationPasswordLineEdit(new TwoAuthenticationPasswordWidget(this)) 0035 , mTwoFactorAuthenticationWidget(new QWidget(this)) 0036 , mAuthenticationAccountWidget(new QWidget(this)) 0037 , mAuthenticationWidget(new AuthenticationOauthWidget(this)) 0038 { 0039 auto mainLayout = new QFormLayout(this); 0040 mainLayout->setObjectName(QStringLiteral("mainLayout")); 0041 0042 mServerUrl->setObjectName(QStringLiteral("mServerUrl")); 0043 mainLayout->addRow(i18n("Server URL:"), mServerUrl); 0044 0045 mAccountName->setObjectName(QStringLiteral("mAccountName")); 0046 mainLayout->addRow(i18n("Account Name:"), mAccountName); 0047 mAccountName->setPlaceholderText(i18n("Account name")); 0048 connect(mAccountName, &QLineEdit::textChanged, this, &RuqolaLoginWidget::slotUpdateLoginButton); 0049 0050 mUserName->setObjectName(QStringLiteral("mUserName")); 0051 mainLayout->addRow(i18n("Username or Email:"), mUserName); 0052 mUserName->setPlaceholderText(i18n("Username or email")); 0053 0054 // Type of account 0055 mAuthenticationAccountWidget->setObjectName(QStringLiteral("mAuthenticationAccountWidget")); 0056 0057 auto authenticationAccountLayout = new QVBoxLayout(mAuthenticationAccountWidget); 0058 authenticationAccountLayout->setObjectName(QStringLiteral("authenticationAccountLayout")); 0059 0060 auto authenticationAccountLabel = new QLabel(i18n("Authentication Method"), this); 0061 authenticationAccountLabel->setTextFormat(Qt::PlainText); 0062 authenticationAccountLabel->setObjectName(QStringLiteral("authenticationAccountLabel")); 0063 authenticationAccountLayout->addWidget(authenticationAccountLabel); 0064 0065 mAuthenticationWidget->setObjectName(QStringLiteral("mAuthenticationWidget")); 0066 authenticationAccountLayout->addWidget(mAuthenticationWidget); 0067 mainLayout->addWidget(mAuthenticationAccountWidget); 0068 mAuthenticationAccountWidget->setVisible(false); 0069 0070 // Password 0071 mPasswordLineEditWidget->setObjectName(QStringLiteral("mPasswordLineEditWidget")); 0072 connect(mPasswordLineEditWidget->passwordLineEdit()->lineEdit(), &QLineEdit::returnPressed, this, &RuqolaLoginWidget::slotLogin); 0073 mainLayout->addRow(i18n("Password:"), mPasswordLineEditWidget); 0074 connect(mPasswordLineEditWidget, &PasswordLineEditWidget::resetPasswordRequested, this, &RuqolaLoginWidget::slotResetPasswordRequested); 0075 0076 // Two Factor authentication 0077 mTwoFactorAuthenticationWidget->setObjectName(QStringLiteral("mTwoFactorAuthenticationWidget")); 0078 mTwoFactorAuthenticationWidget->setVisible(false); 0079 0080 auto twoFactorAuthenticationLayout = new QVBoxLayout(mTwoFactorAuthenticationWidget); 0081 twoFactorAuthenticationLayout->setObjectName(QStringLiteral("twoFactorAuthenticationLayout")); 0082 twoFactorAuthenticationLayout->setContentsMargins(QMargins{}); 0083 0084 auto twoFactorAuthenticationLabel = 0085 new QLabel(i18n("You have enabled second factor authentication.\nPlease enter the generated code or a backup code."), this); 0086 twoFactorAuthenticationLabel->setObjectName(QStringLiteral("twoFactorAuthenticationLabel")); 0087 twoFactorAuthenticationLayout->addWidget(twoFactorAuthenticationLabel); 0088 0089 mTwoFactorAuthenticationPasswordLineEdit->setObjectName(QStringLiteral("mTwoFactorAuthenticationPasswordLineEdit")); 0090 twoFactorAuthenticationLayout->addWidget(mTwoFactorAuthenticationPasswordLineEdit); 0091 0092 mainLayout->addWidget(mTwoFactorAuthenticationWidget); 0093 0094 mLoginButton->setObjectName(QStringLiteral("mLoginButton")); 0095 mainLayout->addWidget(mLoginButton); 0096 connect(mLoginButton, &QPushButton::clicked, this, &RuqolaLoginWidget::slotLogin); 0097 0098 mBusyIndicatorWidget->setObjectName(QStringLiteral("mBusyIndicatorWidget")); 0099 mainLayout->addWidget(mBusyIndicatorWidget); 0100 // Hide by default 0101 mBusyIndicatorWidget->hide(); 0102 0103 mFailedError->setObjectName(QStringLiteral("mFailedError")); 0104 QPalette pal = mFailedError->palette(); 0105 pal.setColor(foregroundRole(), ColorsAndMessageViewStyle::self().schemeView().foreground(KColorScheme::NegativeText).color()); 0106 mFailedError->setPalette(pal); 0107 QFont font = mFailedError->font(); 0108 font.setBold(true); 0109 mFailedError->setFont(font); 0110 0111 mainLayout->addWidget(mFailedError); 0112 // Hide by default 0113 mFailedError->hide(); 0114 } 0115 0116 RuqolaLoginWidget::~RuqolaLoginWidget() = default; 0117 0118 void RuqolaLoginWidget::slotUpdateLoginButton() 0119 { 0120 mLoginButton->setEnabled(!mAccountName->text().isEmpty()); 0121 } 0122 0123 void RuqolaLoginWidget::setRocketChatAccount(RocketChatAccount *rocketChatAccount) 0124 { 0125 mRocketChatAccount = rocketChatAccount; 0126 mAccountName->setText(mRocketChatAccount->displayName()); 0127 mAccountName->setReadOnly(!mRocketChatAccount->displayName().isEmpty()); 0128 mServerUrl->setText(mRocketChatAccount->serverUrl()); 0129 mServerUrl->setReadOnly(true); 0130 0131 mUserName->setText(mRocketChatAccount->userName()); 0132 disconnect(mUpdatePasswordConnection); 0133 mPasswordLineEditWidget->passwordLineEdit()->setPassword(mRocketChatAccount->password()); 0134 qCDebug(RUQOLA_PASSWORD_WIDGETS_LOG) << " RuqolaLoginWidget::setRocketChatAccount: password is empty ? " << mRocketChatAccount->password().isEmpty(); 0135 mUpdatePasswordConnection = connect(mRocketChatAccount, &RocketChatAccount::passwordChanged, mPasswordLineEditWidget, [this]() { 0136 qCDebug(RUQOLA_PASSWORD_WIDGETS_LOG) << " RuqolaLoginWidget::setRocketChatAccount: password has changed => password is empty ? " 0137 << mRocketChatAccount->password().isEmpty(); 0138 mPasswordLineEditWidget->passwordLineEdit()->setPassword(mRocketChatAccount->password()); 0139 }); 0140 0141 mTwoFactorAuthenticationPasswordLineEdit->setRocketChatAccount(mRocketChatAccount); 0142 mPasswordLineEditWidget->setAllowPasswordReset(mRocketChatAccount->allowPasswordReset() && mRocketChatAccount->allowPasswordChange()); 0143 } 0144 0145 void RuqolaLoginWidget::slotLogin() 0146 { 0147 mRocketChatAccount->setAccountName(mAccountName->isEnabled() ? mAccountName->text() : mRocketChatAccount->accountName()); 0148 mRocketChatAccount->setServerUrl(mServerUrl->text()); 0149 mRocketChatAccount->setUserName(mUserName->text()); 0150 mRocketChatAccount->setPassword(mPasswordLineEditWidget->passwordLineEdit()->password()); 0151 if (mTwoFactorAuthenticationPasswordLineEdit->isHidden()) { 0152 mTwoFactorAuthenticationPasswordLineEdit->clear(); 0153 } else { 0154 mRocketChatAccount->setTwoFactorAuthenticationCode(mTwoFactorAuthenticationPasswordLineEdit->code()); 0155 } 0156 mRocketChatAccount->tryLogin(); 0157 } 0158 0159 void RuqolaLoginWidget::changeWidgetStatus(bool enabled) 0160 { 0161 mServerUrl->setEnabled(enabled); 0162 mUserName->setEnabled(enabled); 0163 mPasswordLineEditWidget->setEnabled(enabled); 0164 mLoginButton->setEnabled(enabled && !mAccountName->text().isEmpty()); 0165 } 0166 0167 void RuqolaLoginWidget::setLoginStatus(DDPAuthenticationManager::LoginStatus status) 0168 { 0169 mFailedError->setHidden(true); 0170 switch (status) { 0171 case DDPAuthenticationManager::LoginStatus::Connecting: 0172 case DDPAuthenticationManager::LoginStatus::LoginOngoing: 0173 mBusyIndicatorWidget->show(); 0174 changeWidgetStatus(false); 0175 mTwoFactorAuthenticationWidget->setVisible(false); 0176 break; 0177 case DDPAuthenticationManager::LoginStatus::LoggedOut: 0178 case DDPAuthenticationManager::LoginStatus::LoggedIn: 0179 mBusyIndicatorWidget->hide(); 0180 changeWidgetStatus(true); 0181 mTwoFactorAuthenticationWidget->setVisible(false); 0182 break; 0183 case DDPAuthenticationManager::LoginStatus::LoginFailedInvalidUserOrPassword: 0184 mBusyIndicatorWidget->hide(); 0185 changeWidgetStatus(true); 0186 showError(i18n("Login Failed: invalid username or password")); 0187 mTwoFactorAuthenticationWidget->setVisible(false); 0188 break; 0189 case DDPAuthenticationManager::LoginFailedInvalidOtp: 0190 showError(i18n("Login failed: Invalid OTP code.")); 0191 Q_FALLTHROUGH(); 0192 case DDPAuthenticationManager::LoginStatus::LoginOtpRequired: 0193 mBusyIndicatorWidget->hide(); 0194 changeWidgetStatus(true); 0195 mTwoFactorAuthenticationWidget->setVisible(true); 0196 break; 0197 case DDPAuthenticationManager::LoginStatus::FailedToLoginPluginProblem: 0198 mBusyIndicatorWidget->hide(); 0199 changeWidgetStatus(true); 0200 showError(i18n("Installation Problem found. No plugins found here.")); 0201 mTwoFactorAuthenticationWidget->setVisible(false); 0202 break; 0203 case DDPAuthenticationManager::LoginStatus::GenericError: 0204 mBusyIndicatorWidget->hide(); 0205 changeWidgetStatus(true); 0206 showError(i18n("Login Failed: generic error")); 0207 mTwoFactorAuthenticationWidget->setVisible(false); 0208 break; 0209 case DDPAuthenticationManager::LoginFailedLoginBlockForIp: 0210 mBusyIndicatorWidget->hide(); 0211 changeWidgetStatus(true); 0212 showError(i18n("Login Failed: Login has been temporarily blocked For IP.")); 0213 mTwoFactorAuthenticationWidget->setVisible(false); 0214 break; 0215 case DDPAuthenticationManager::LoginFailedLoginBlockedForUser: 0216 mBusyIndicatorWidget->hide(); 0217 changeWidgetStatus(true); 0218 showError(i18n("Login Failed: Login has been temporarily blocked For User.")); 0219 mTwoFactorAuthenticationWidget->setVisible(false); 0220 break; 0221 case DDPAuthenticationManager::LoginStatus::LoginFailedUserNotActivated: 0222 mBusyIndicatorWidget->hide(); 0223 changeWidgetStatus(true); 0224 showError(i18n("Login Failed: User is not activated.")); 0225 mTwoFactorAuthenticationWidget->setVisible(false); 0226 break; 0227 case DDPAuthenticationManager::LoginStatus::LoginFailedLoginAppNotAllowedToLogin: 0228 mBusyIndicatorWidget->hide(); 0229 changeWidgetStatus(true); 0230 showError(i18n("Login Failed: App user is not allowed to login.")); 0231 mTwoFactorAuthenticationWidget->setVisible(false); 0232 break; 0233 case DDPAuthenticationManager::LoginOtpAuthOngoing: 0234 case DDPAuthenticationManager::LogoutOngoing: 0235 case DDPAuthenticationManager::LogoutCleanUpOngoing: 0236 case DDPAuthenticationManager::LoggedOutAndCleanedUp: 0237 // TODO 0238 mTwoFactorAuthenticationWidget->setVisible(false); 0239 mBusyIndicatorWidget->hide(); 0240 changeWidgetStatus(true); 0241 break; 0242 } 0243 } 0244 0245 void RuqolaLoginWidget::showError(const QString &text) 0246 { 0247 mFailedError->setVisible(true); 0248 mFailedError->setText(text); 0249 } 0250 0251 void RuqolaLoginWidget::slotResetPasswordRequested(const QString &email) 0252 { 0253 mRocketChatAccount->requestNewPassword(email); 0254 } 0255 0256 #include "moc_ruqolaloginwidget.cpp"