1#include "ServerConfigDlg.h"
2#include "ui_ServerConfigDlg.h"
3
4#include <GitBase.h>
5#include <GitConfig.h>
6#include <GitQlientStyles.h>
7#include <GitQlientSettings.h>
8#include <GitHubRestApi.h>
9#include <GitLabRestApi.h>
10#include <GitServerCache.h>
11
12#include <QLogger.h>
13
14#include <QTimer>
15#include <QNetworkAccessManager>
16#include <QNetworkRequest>
17#include <QNetworkReply>
18#include <QJsonDocument>
19#include <QJsonObject>
20#include <QJsonArray>
21#include <QFile>
22#include <QMessageBox>
23#include <QDesktopServices>
24
25#include <utility>
26
27using namespace QLogger;
28using namespace GitServer;
29
30namespace
31{
32enum GitServerPlatform
33{
34 GitHub,
35 GitHubEnterprise,
36 GitLab,
37 Bitbucket
38};
39
40static const QMap<GitServerPlatform, const char *> repoUrls { { GitHub, "https://api.github.com" },
41 { GitHubEnterprise, "" },
42 { GitLab, "https://gitlab.com/api/v4" } };
43}
44
45ServerConfigDlg::ServerConfigDlg(const QSharedPointer<GitServerCache> &gitServerCache,
46 const GitServer::ConfigData &data, QWidget *parent)
47 : QDialog(parent)
48 , ui(new Ui::ServerConfigDlg)
49 , mGitServerCache(gitServerCache)
50 , mData(data)
51 , mManager(new QNetworkAccessManager())
52{
53 setStyleSheet(GitQlientStyles::getStyles());
54
55 ui->setupUi(this);
56
57 connect(ui->cbServer, &QComboBox::currentTextChanged, this, &ServerConfigDlg::onServerChanged);
58
59 ui->leEndPoint->setHidden(true);
60
61 GitQlientSettings settings("");
62 ui->leUserName->setText(mData.user);
63 ui->leUserToken->setText(mData.token);
64 ui->leEndPoint->setText(
65 settings.globalValue(QString("%1/endpoint").arg(mData.serverUrl), repoUrls.value(GitHub)).toString());
66
67 ui->cbServer->insertItem(GitHub, "GitHub", repoUrls.value(GitHub));
68 ui->cbServer->insertItem(GitHubEnterprise, "GitHub Enterprise", repoUrls.value(GitHubEnterprise));
69
70 if (mData.serverUrl.contains("github"))
71 {
72 const auto index = repoUrls.key(ui->leEndPoint->text().toUtf8(), GitHubEnterprise);
73 ui->cbServer->setCurrentIndex(index);
74 }
75 else
76 {
77 ui->cbServer->insertItem(GitLab, "GitLab", repoUrls.value(GitLab));
78 ui->cbServer->setCurrentIndex(GitLab);
79 ui->cbServer->setVisible(false);
80 }
81
82 ui->lAccessToken->setText(tr("How to get a token?"));
83 connect(ui->lAccessToken, &ButtonLink::clicked, [this]() {
84 const auto url = mData.serverUrl.contains("github")
85 ? "https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token"
86 : "https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html";
87 QDesktopServices::openUrl(QUrl(QString::fromUtf8(url)));
88 });
89
90 connect(ui->leUserToken, &QLineEdit::editingFinished, this, &ServerConfigDlg::checkToken);
91 connect(ui->leUserToken, &QLineEdit::returnPressed, this, &ServerConfigDlg::accept);
92 connect(ui->pbAccept, &QPushButton::clicked, this, &ServerConfigDlg::accept);
93 connect(ui->pbCancel, &QPushButton::clicked, this, &ServerConfigDlg::reject);
94 connect(ui->pbTest, &QPushButton::clicked, this, &ServerConfigDlg::testToken);
95}
96
97ServerConfigDlg::~ServerConfigDlg()
98{
99 delete mManager;
100 delete ui;
101}
102
103void ServerConfigDlg::checkToken()
104{
105 if (ui->leUserToken->text().isEmpty())
106 ui->leUserName->setStyleSheet("border: 1px solid red;");
107}
108
109void ServerConfigDlg::accept()
110{
111 const auto endpoint = ui->cbServer->currentIndex() == GitHubEnterprise ? ui->leEndPoint->text()
112 : ui->cbServer->currentData().toString();
113 GitQlientSettings settings("");
114 settings.setGlobalValue(QString("%1/user").arg(mData.serverUrl), ui->leUserName->text());
115 settings.setGlobalValue(QString("%1/token").arg(mData.serverUrl), ui->leUserToken->text());
116 settings.setGlobalValue(QString("%1/endpoint").arg(mData.serverUrl), endpoint);
117
118 connect(mGitServerCache.get(), &GitServerCache::errorOccurred, this, &ServerConfigDlg::onGitServerError);
119 connect(mGitServerCache.get(), &GitServerCache::connectionTested, this, [this]() { onDataValidated(); });
120
121 mGitServerCache->init(mData.serverUrl, mData.repoInfo);
122}
123
124void ServerConfigDlg::testToken()
125{
126 if (ui->leUserToken->text().isEmpty())
127 ui->leUserName->setStyleSheet("border: 1px solid red;");
128 else
129 {
130 const auto endpoint = ui->cbServer->currentIndex() == GitHubEnterprise ? ui->leEndPoint->text()
131 : ui->cbServer->currentData().toString();
132 IRestApi *api = nullptr;
133
134 if (ui->cbServer->currentIndex() == GitLab)
135 {
136 api = new GitLabRestApi(ui->leUserName->text(), mData.repoInfo.second, mData.serverUrl,
137 { ui->leUserName->text(), ui->leUserToken->text(), endpoint }, this);
138 }
139 else
140 {
141 api = new GitHubRestApi(mData.repoInfo.first, mData.repoInfo.second,
142 { ui->leUserName->text(), ui->leUserToken->text(), endpoint }, this);
143 }
144
145 api->testConnection();
146
147 connect(api, &IRestApi::connectionTested, this, &ServerConfigDlg::onTestSucceeded);
148 connect(api, &IRestApi::errorOccurred, this, &ServerConfigDlg::onGitServerError);
149 }
150}
151
152void ServerConfigDlg::onServerChanged()
153{
154 ui->leEndPoint->setVisible(ui->cbServer->currentIndex() == GitHubEnterprise);
155}
156
157void ServerConfigDlg::onTestSucceeded()
158{
159 ui->lTestResult->setText(tr("Token confirmed!"));
160 QTimer::singleShot(3000, ui->lTestResult, &QLabel::clear);
161}
162
163void ServerConfigDlg::onGitServerError(const QString &error)
164{
165 QMessageBox::warning(this, tr("API access error!"), error);
166}
167
168void ServerConfigDlg::onDataValidated()
169{
170 emit configured();
171
172 QDialog::accept();
173}
174