File indexing completed on 2024-12-01 04:36:53

0001 /*
0002    SPDX-FileCopyrightText: 2022-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "myaccountpersonalaccesstokenconfigurewidget.h"
0008 #include "connection.h"
0009 #include "model/personalaccesstokeninfosfilterproxymodel.h"
0010 #include "model/personalaccesstokeninfosmodel.h"
0011 #include "myaccountpersonalaccesscreatedialog.h"
0012 #include "myaccountpersonalaccesstokentreeview.h"
0013 #include "personalaccesstoken/generatepersonalaccesstokenjob.h"
0014 #include "personalaccesstoken/getpersonalaccesstokensjob.h"
0015 #include "personalaccesstoken/regeneratepersonalaccesstokenjob.h"
0016 #include "personalaccesstoken/removepersonalaccesstokenjob.h"
0017 #include <KLineEditEventHandler>
0018 
0019 #include "dialogs/confirmpassworddialog.h"
0020 #include "personalaccesstokens/personalaccesstokeninfos.h"
0021 
0022 #include "rocketchataccount.h"
0023 #include "ruqolawidgets_debug.h"
0024 #include <KLocalizedString>
0025 #include <KMessageBox>
0026 #include <QLineEdit>
0027 #include <QVBoxLayout>
0028 
0029 MyAccountPersonalAccessTokenConfigureWidget::MyAccountPersonalAccessTokenConfigureWidget(RocketChatAccount *account, QWidget *parent)
0030     : QWidget{parent}
0031     , mRocketChatAccount(account)
0032     , mSearchLineWidget(new QLineEdit(this))
0033     , mPersonalAccessTokenTreeView(new MyAccountPersonalAccessTokenTreeView(this))
0034     , mPersonalAccessTokenModel(new PersonalAccessTokenInfosModel(this))
0035     , mPersonalAccessTokenFilterProxyModel(new PersonalAccessTokenInfosFilterProxyModel(this))
0036 
0037 {
0038     auto mainLayout = new QVBoxLayout(this);
0039     mainLayout->setObjectName(QStringLiteral("mainLayout"));
0040     mainLayout->setContentsMargins({});
0041     mainLayout->setSpacing(0);
0042 
0043     mSearchLineWidget->setObjectName(QStringLiteral("mSearchLineWidget"));
0044     mainLayout->addWidget(mSearchLineWidget);
0045     mSearchLineWidget->setPlaceholderText(i18n("Search Personal Access Token..."));
0046     mPersonalAccessTokenTreeView->setObjectName(QStringLiteral("mPersonalAccessTokenTreeView"));
0047     mPersonalAccessTokenTreeView->setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::TopEdge}));
0048     mainLayout->addWidget(mPersonalAccessTokenTreeView);
0049 
0050     KLineEditEventHandler::catchReturnKey(mSearchLineWidget);
0051 
0052     mPersonalAccessTokenModel->setObjectName(QStringLiteral("mPersonalAccessTokenModel"));
0053 
0054     mPersonalAccessTokenFilterProxyModel->setObjectName(QStringLiteral("proxyModel"));
0055     mPersonalAccessTokenFilterProxyModel->setSourceModel(mPersonalAccessTokenModel);
0056     mPersonalAccessTokenTreeView->setModel(mPersonalAccessTokenFilterProxyModel);
0057     mPersonalAccessTokenTreeView->setColumnHidden(PersonalAccessTokenInfosModel::CreateAtDateTime, true);
0058     connect(mPersonalAccessTokenTreeView,
0059             &MyAccountPersonalAccessTokenTreeView::createToken,
0060             this,
0061             &MyAccountPersonalAccessTokenConfigureWidget::slotCreateToken);
0062     connect(mPersonalAccessTokenTreeView,
0063             &MyAccountPersonalAccessTokenTreeView::removeToken,
0064             this,
0065             &MyAccountPersonalAccessTokenConfigureWidget::slotRemoveToken);
0066     connect(mPersonalAccessTokenTreeView,
0067             &MyAccountPersonalAccessTokenTreeView::regenerateToken,
0068             this,
0069             &MyAccountPersonalAccessTokenConfigureWidget::slotRegenerateToken);
0070     connect(mSearchLineWidget, &QLineEdit::textChanged, this, &MyAccountPersonalAccessTokenConfigureWidget::slotTextChanged);
0071 }
0072 
0073 MyAccountPersonalAccessTokenConfigureWidget::~MyAccountPersonalAccessTokenConfigureWidget() = default;
0074 
0075 void MyAccountPersonalAccessTokenConfigureWidget::slotTextChanged(const QString &str)
0076 {
0077     mPersonalAccessTokenFilterProxyModel->setFilterString(str);
0078 }
0079 
0080 void MyAccountPersonalAccessTokenConfigureWidget::initialize()
0081 {
0082     if (mRocketChatAccount) {
0083         auto job = new RocketChatRestApi::GetPersonalAccessTokensJob(this);
0084         mRocketChatAccount->restApi()->initializeRestApiJob(job);
0085         connect(job, &RocketChatRestApi::GetPersonalAccessTokensJob::getPersonalAccessTokensDone, this, [this](const QJsonObject &obj) {
0086             PersonalAccessTokenInfos info;
0087             info.parsePersonalAccessTokenInfos(obj);
0088             mPersonalAccessTokenModel->insertPersonalAccessTokenInfos(info);
0089         });
0090         if (!job->start()) {
0091             qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start GetPersonalAccessTokensJob job";
0092         }
0093     }
0094 }
0095 
0096 void MyAccountPersonalAccessTokenConfigureWidget::slotCreateToken()
0097 {
0098     QPointer<MyAccountPersonalAccessCreateDialog> createDialog = new MyAccountPersonalAccessCreateDialog(this);
0099     if (createDialog->exec()) {
0100         if (mRocketChatAccount) {
0101             QString password;
0102             const bool twoFactorAuthenticationEnforcePasswordFallback = true; // mRocketChatAccount->twoFactorAuthenticationEnforcePasswordFallback();
0103             if (twoFactorAuthenticationEnforcePasswordFallback) {
0104                 QPointer<ConfirmPasswordDialog> dialog(new ConfirmPasswordDialog(this));
0105                 if (dialog->exec()) {
0106                     password = dialog->password();
0107                 }
0108                 delete dialog;
0109             }
0110             if (!password.isEmpty()) {
0111                 auto job = new RocketChatRestApi::GeneratePersonalAccessTokenJob(this);
0112                 if (twoFactorAuthenticationEnforcePasswordFallback) {
0113                     job->setAuthMethod(QStringLiteral("password"));
0114                     job->setAuthCode(QString::fromLatin1(Utils::convertSha256Password(password)));
0115                 }
0116                 job->setTokenName(createDialog->tokenName());
0117                 job->setBypassTwoFactor(createDialog->bypassTwoFactor());
0118 
0119                 mRocketChatAccount->restApi()->initializeRestApiJob(job);
0120                 connect(job, &RocketChatRestApi::GeneratePersonalAccessTokenJob::generateTokenDone, this, [this](const QJsonObject &obj) {
0121                     const QString token = obj[QLatin1String("token")].toString();
0122                     KMessageBox::information(this,
0123                                              i18n("<qt>Please save your token carefully as you will no longer be able to view it afterwards.<br>"
0124                                                   "<b>Token:</b> %1<br>"
0125                                                   "<b>Your user Id:</b> %2</qt>",
0126                                                   token,
0127                                                   mRocketChatAccount->userId()),
0128                                              i18n("Personal Token Created"));
0129                     initialize();
0130                 });
0131                 if (!job->start()) {
0132                     qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start GeneratePersonalAccessTokenJob job";
0133                 }
0134             }
0135         }
0136     }
0137     delete createDialog;
0138 }
0139 
0140 void MyAccountPersonalAccessTokenConfigureWidget::slotRemoveToken(const QString &tokenName)
0141 {
0142     if (mRocketChatAccount) {
0143         QString password;
0144         const bool twoFactorAuthenticationEnforcePasswordFallback = true; // mRocketChatAccount->twoFactorAuthenticationEnforcePasswordFallback();
0145         if (twoFactorAuthenticationEnforcePasswordFallback) {
0146             QPointer<ConfirmPasswordDialog> dialog(new ConfirmPasswordDialog(this));
0147             if (dialog->exec()) {
0148                 password = dialog->password();
0149             }
0150             delete dialog;
0151         }
0152 
0153         if (!password.isEmpty()) {
0154             auto job = new RocketChatRestApi::RemovePersonalAccessTokenJob(this);
0155             job->setTokenName(tokenName);
0156             if (twoFactorAuthenticationEnforcePasswordFallback) {
0157                 job->setAuthMethod(QStringLiteral("password"));
0158                 job->setAuthCode(QString::fromLatin1(Utils::convertSha256Password(password)));
0159             }
0160 
0161             mRocketChatAccount->restApi()->initializeRestApiJob(job);
0162             connect(job, &RocketChatRestApi::RemovePersonalAccessTokenJob::removeTokenDone, this, [this, tokenName]() {
0163                 KMessageBox::information(this, i18n("Personal Token removed."), i18n("Remove Personal Token"));
0164                 mPersonalAccessTokenModel->removeToken(tokenName);
0165             });
0166             if (!job->start()) {
0167                 qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start RemovePersonalAccessTokenJob job";
0168             }
0169         }
0170     }
0171 }
0172 
0173 void MyAccountPersonalAccessTokenConfigureWidget::slotRegenerateToken(const QString &tokenName)
0174 {
0175     if (mRocketChatAccount) {
0176         QString password;
0177         const bool twoFactorAuthenticationEnforcePasswordFallback = true; // mRocketChatAccount->twoFactorAuthenticationEnforcePasswordFallback();
0178         if (twoFactorAuthenticationEnforcePasswordFallback) {
0179             QPointer<ConfirmPasswordDialog> dialog(new ConfirmPasswordDialog(this));
0180             if (dialog->exec()) {
0181                 password = dialog->password();
0182             }
0183             delete dialog;
0184         }
0185 
0186         if (!password.isEmpty()) {
0187             auto job = new RocketChatRestApi::RegeneratePersonalAccessTokenJob(this);
0188             if (twoFactorAuthenticationEnforcePasswordFallback) {
0189                 job->setAuthMethod(QStringLiteral("password"));
0190                 job->setAuthCode(QString::fromLatin1(Utils::convertSha256Password(password)));
0191             }
0192             job->setTokenName(tokenName);
0193             mRocketChatAccount->restApi()->initializeRestApiJob(job);
0194             connect(job, &RocketChatRestApi::RegeneratePersonalAccessTokenJob::regenerateTokenDone, this, [this](const QJsonObject &obj) {
0195                 const QString token = obj[QLatin1String("token")].toString();
0196                 KMessageBox::information(this,
0197                                          i18n("<qt>Please save your token carefully as you will no longer be able to view it afterwards.<br>"
0198                                               "<b>Token:</b> %1<br>"
0199                                               "<b>Your user Id:</b> %2</qt>",
0200                                               token,
0201                                               mRocketChatAccount->userId()),
0202                                          i18n("Personal Token Regenerated"));
0203                 initialize();
0204             });
0205             if (!job->start()) {
0206                 qCWarning(RUQOLAWIDGETS_LOG) << "Impossible to start RegeneratePersonalAccessTokenJob job";
0207             }
0208         }
0209     }
0210 }
0211 
0212 #include "moc_myaccountpersonalaccesstokenconfigurewidget.cpp"