File indexing completed on 2024-05-05 04:39:54
0001 /* 0002 SPDX-FileCopyrightText: 2012-2013 Miquel Sabaté <mikisabate@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "ghdialog.h" 0008 0009 #include <ghaccount.h> 0010 #include <ghresource.h> 0011 0012 #include <KLocalizedString> 0013 #include <KMessageBox> 0014 #include <KPasswordDialog> 0015 0016 #include <QLabel> 0017 #include <QDialogButtonBox> 0018 #include <QPushButton> 0019 #include <QVBoxLayout> 0020 #include <QPointer> 0021 #include <QInputDialog> 0022 0023 static QString invalidAccountText() 0024 { 0025 return i18n("You have not authorized KDevelop to use your GitHub account. " 0026 "If you authorize KDevelop, you will be able to fetch your " 0027 "public/private repositories and the repositories from your " 0028 "organizations."); 0029 } 0030 0031 static QString tokenLinkStatementText() 0032 { 0033 return i18nc("%1 is the URL with the GitHub token settings", 0034 "You can check the authorization for this application and " 0035 "others at %1", 0036 QStringLiteral("https://github.com/settings/tokens.")); 0037 } 0038 0039 namespace gh 0040 { 0041 0042 Dialog::Dialog(QWidget *parent, Account *account) 0043 : QDialog(parent) 0044 , m_account(account) 0045 { 0046 auto mainWidget = new QWidget(this); 0047 auto mainLayout = new QVBoxLayout; 0048 setLayout(mainLayout); 0049 mainLayout->addWidget(mainWidget); 0050 0051 auto buttonBox = new QDialogButtonBox(); 0052 0053 if (m_account->validAccount()) { 0054 m_text = new QLabel(i18n("You are logged in as <b>%1</b>.<br/>%2", 0055 m_account->name(), tokenLinkStatementText()), this); 0056 0057 auto logOutButton = new QPushButton; 0058 logOutButton->setText(i18nc("@action:button", "Log Out")); 0059 logOutButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel"))); 0060 buttonBox->addButton(logOutButton, QDialogButtonBox::ActionRole); 0061 connect(logOutButton, &QPushButton::clicked, this, &Dialog::revokeAccess); 0062 0063 auto forceSyncButton = new QPushButton; 0064 forceSyncButton->setText(i18nc("@action:button", "Force Sync")); 0065 forceSyncButton->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); 0066 buttonBox->addButton(forceSyncButton, QDialogButtonBox::ActionRole); 0067 connect(forceSyncButton, &QPushButton::clicked, this, &Dialog::syncUser); 0068 0069 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0070 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0071 } else { 0072 m_text = new QLabel(invalidAccountText(), this); 0073 0074 buttonBox->addButton(QDialogButtonBox::Cancel); 0075 0076 auto authorizeButton = new QPushButton; 0077 buttonBox->addButton(authorizeButton, QDialogButtonBox::ActionRole); 0078 authorizeButton->setText(i18nc("@action:button", "Authorize")); 0079 authorizeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok"))); 0080 connect(authorizeButton, &QPushButton::clicked, this, &Dialog::authorizeClicked); 0081 } 0082 0083 m_text->setWordWrap(true); 0084 m_text->setOpenExternalLinks(true); 0085 setMinimumWidth(350); 0086 mainLayout->addWidget(m_text); 0087 0088 mainLayout->addWidget(buttonBox); 0089 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0090 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0091 0092 setWindowTitle(i18nc("@title:window", "GitHub Account")); 0093 } 0094 0095 void Dialog::authorizeClicked() 0096 { 0097 QPointer<KPasswordDialog> dlg = new KPasswordDialog(this, KPasswordDialog::ShowUsernameLine); 0098 dlg->setPrompt(i18n("Enter a login and a password")); 0099 if(dlg->exec()) { 0100 m_text->setAlignment(Qt::AlignCenter); 0101 m_text->setText(i18n("Waiting for response")); 0102 m_account->setName(dlg->username()); 0103 0104 Resource *rs = m_account->resource(); 0105 rs->authenticate(dlg->username(), dlg->password()); 0106 connect(rs, &Resource::twoFactorAuthRequested, 0107 this, &Dialog::twoFactorResponse); 0108 connect(rs, &Resource::authenticated, 0109 this, &Dialog::authorizeResponse); 0110 } 0111 delete dlg; 0112 } 0113 0114 void Dialog::authorizeResponse(const QByteArray &id, const QByteArray &token, const QString &tokenName) 0115 { 0116 Q_UNUSED(tokenName); 0117 0118 Resource *rs = m_account->resource(); 0119 disconnect(rs, &Resource::authenticated, 0120 this, &Dialog::authorizeResponse); 0121 0122 if (id.isEmpty()) { 0123 m_text->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0124 m_text->setText(invalidAccountText()); 0125 m_account->setName(QString()); 0126 KMessageBox::error(this, i18n("Authentication failed. Please try again.\n\n" 0127 "Could not create token: \"%1\"\n%2", tokenName, 0128 tokenLinkStatementText()), 0129 i18nc("@title:window", "GitHub Authorization Failed")); 0130 return; 0131 } 0132 else{ 0133 KMessageBox::information(this, i18n("Authentication succeeded.\n\n" 0134 "Created token: \"%1\"\n%2", tokenName, 0135 tokenLinkStatementText()), 0136 i18nc("@title:window", "GitHub Account Authorized")); 0137 } 0138 m_account->saveToken(id, token); 0139 syncUser(); 0140 } 0141 0142 void Dialog::twoFactorResponse(const QString &transferHeader) 0143 { 0144 auto code = QInputDialog::getText(this, i18nc("@title:window", "Authentication Code"), i18nc("@label:textbox", "OTP Code:")); 0145 Resource* rs = m_account->resource(); 0146 disconnect(rs, &Resource::twoFactorAuthRequested, 0147 this, &Dialog::twoFactorResponse); 0148 rs->twoFactorAuthenticate(transferHeader, code); 0149 } 0150 0151 void Dialog::syncUser() 0152 { 0153 Resource *rs = m_account->resource(); 0154 connect(rs, &Resource::orgsUpdated, 0155 this, &Dialog::updateOrgs); 0156 m_text->setAlignment(Qt::AlignCenter); 0157 m_text->setText(i18n("Waiting for response")); 0158 rs->getOrgs(m_account->token()); 0159 } 0160 0161 void Dialog::updateOrgs(const QStringList& orgs) 0162 { 0163 Resource *rs = m_account->resource(); 0164 disconnect(rs, &Resource::orgsUpdated, 0165 this, &Dialog::updateOrgs); 0166 0167 if (!orgs.isEmpty()) 0168 m_account->setOrgs(orgs); 0169 emit shouldUpdate(); 0170 close(); 0171 } 0172 0173 void Dialog::revokeAccess() 0174 { 0175 QPointer<KPasswordDialog> dlg = new KPasswordDialog(this); 0176 dlg->setPrompt(i18n("Please, write your password here.")); 0177 if(dlg->exec()) { 0178 m_account->invalidate(dlg->password()); 0179 emit shouldUpdate(); 0180 close(); 0181 } 0182 delete dlg; 0183 } 0184 0185 } // End of namespace gh 0186 0187 #include "moc_ghdialog.cpp"