]> git.sven.stormbind.net Git - sven/vym.git/blob - src/jira-agent.cpp
New upstream version 2.9.22
[sven/vym.git] / src / jira-agent.cpp
1 #include "jira-agent.h"
2
3 #include "branchitem.h"
4 #include "mainwindow.h"
5 #include "vymmodel.h"
6
7 #include <QHash>
8 #include <QMessageBox>
9 #include <QSslSocket>
10
11 extern Main *mainWindow;
12 extern QDir vymBaseDir;
13 extern Settings settings;
14 extern QTextStream vout;
15 extern bool debug;
16
17 bool JiraAgent::available()
18 {
19     if (!QSslSocket::supportsSsl())
20         return false;
21     if ( settings.value("/atlassian/jira/servers/size", 0).toInt() < 1)
22         return false;
23
24     return true;
25 }
26
27 JiraAgent::JiraAgent()
28 {
29     //qDebug ()<< "Constr. JiraAgent";
30
31     init();
32 }
33
34 JiraAgent::~JiraAgent()
35 {
36     //qDebug() << "Destr. JiraAgent";
37
38     if (killTimer)
39         delete killTimer;
40 }
41
42 void JiraAgent::init()
43 {
44     jobType = Undefined;
45     jobStep = -1;
46     abortJob = false;
47
48     killTimer = nullptr;
49
50     networkManager = new QNetworkAccessManager(this);
51
52     modelID = 0;    // invalid ID
53
54     killTimer = new QTimer(this);
55     killTimer->setInterval(15000);
56     killTimer->setSingleShot(true);
57
58     QObject::connect(killTimer, SIGNAL(timeout()), this, SLOT(timeout()));
59
60     // Reset credentials, these are server specific beginning in 2.9.18
61     authUsingPATInt = true;
62     personalAccessTokenInt = QString();
63     userNameInt = QString();
64     passwordInt = QString();
65     serverNameInt = QString();
66
67     // Set API rest point. baseUrlInt later on depends on different JIRA system
68     apiUrl = "/rest/api/2";
69
70 }
71
72 void JiraAgent::setJobType(JobType jt)
73 {
74     jobType = jt;
75 }
76
77 bool JiraAgent::setBranch(BranchItem *bi)
78 {
79     if (!bi) {
80         abortJob = true;
81         return false;
82     } else {
83         branchID = bi->getID();
84         modelID = bi->getModel()->getModelID();
85         return true;
86     }
87 }
88
89
90 bool JiraAgent::setTicket(const QString &id)
91 {
92     // Find ID part in parameter:
93     QRegExp re("(\\w+[-|\\s]\\d+)");
94     if (re.indexIn(id) < 0) {
95         qWarning() << "JiraAgent::setTicket invalid ID: " << id;
96         abortJob = true;
97         return false;
98     }
99
100     ticketID = re.cap(1);
101     ticketID.replace(" ", "-");
102
103     bool foundPattern = false;
104
105     settings.beginGroup("/atlassian/jira");
106
107     // Try to find baseUrl of server by looking through patterns in ticket IDs:
108     int size = settings.beginReadArray("servers");
109     for (int i = 0; i < size; ++i) {
110         settings.setArrayIndex(i);
111         foreach (QString p, settings.value("pattern").toString().split(",")) {
112             if (ticketID.contains(p)) {
113                 foundPattern = true;
114
115                 baseUrlInt = settings.value("baseUrl","-").toString();
116                 serverNameInt = settings.value("name","-").toString();
117
118                 // Read credentials for this server   
119                 authUsingPATInt = 
120                     settings.value("authUsingPAT", true).toBool();
121                 if (authUsingPATInt)
122                     personalAccessTokenInt =
123                         settings.value("PAT", "undefined").toString();
124                 else {
125                     userNameInt =
126                         settings.value("username", "user_johnDoe").toString();
127                     passwordInt = 
128                         settings.value("password", "").toString();
129                 }
130                 break;
131             }
132         }
133     }
134     settings.endArray();
135     settings.endGroup();
136
137     return foundPattern;
138 }
139
140 QString JiraAgent::serverName()
141 {
142     if (baseUrlInt.isEmpty())
143         return QString();
144     else
145         return serverNameInt;
146 }
147
148 QString JiraAgent::url()
149 {
150     return baseUrlInt + "/browse/" + ticketID;
151 }
152
153 void JiraAgent::startJob()
154 {
155     if (jobStep > 0) {
156         unknownStepWarning();
157         finishJob();
158     } else {
159         jobStep = 0;
160         continueJob();
161     }
162 }
163
164 void JiraAgent::continueJob()
165 {
166     if (abortJob) {
167         finishJob();
168         return;
169     }
170
171     jobStep++;
172
173     // qDebug() << "JA::contJob " << jobType << " Step: " << jobStep << "TicketID: " << ticketID;
174
175     switch(jobType) {
176         case GetTicketInfo:
177             switch(jobStep) {
178                 case 1:
179                     // if (!requestedURL.toString().startsWith("http"))
180                     //    requestedURL.setPath("https://" + requestedURL.path());
181                     startGetTicketRequest();
182                     break;
183                 case 2: {
184                     QJsonDocument jsdoc = QJsonDocument (jsobj);
185
186                     // Insert references to original branch and model
187                     jsobj["vymBranchId"] = QJsonValue(branchID);
188                     jsobj["vymTicketUrl"] = QJsonValue(url());
189
190                     emit (jiraTicketReady(QJsonObject(jsobj)));
191                     finishJob();
192                     }
193                     break;
194                 default:
195                     unknownStepWarning();
196                     break;
197             };
198             break;
199         default:
200             qWarning() << "JiraAgent::continueJob   unknown jobType " << jobType;
201     }
202 }
203
204 void JiraAgent::finishJob()
205 {
206     deleteLater();
207 }
208
209 void JiraAgent::unknownStepWarning()
210 {
211     qWarning() << "JA::contJob  unknow step in jobType = " 
212         << jobType 
213         << "jobStep = " << jobStep;
214 }
215
216 void JiraAgent::startGetTicketRequest()
217 {
218     QUrl u = QUrl(baseUrlInt + apiUrl + "/issue/" + ticketID);
219
220     QNetworkRequest request = QNetworkRequest(u);
221
222     // Basic authentication in header
223     QString headerData;
224     if (authUsingPATInt)
225         headerData = QString("Bearer %1").arg(personalAccessTokenInt);
226     else {
227         QString concatenated = userNameInt + ":" + passwordInt;
228         QByteArray data = concatenated.toLocal8Bit().toBase64();
229         headerData = "Basic " + data;
230     }
231
232     request.setRawHeader("Authorization", headerData.toLocal8Bit());
233
234     if (debug)
235         qDebug() << "JA::startGetTicketRequest: url = " + request.url().toString();
236
237     killTimer->start();
238
239     connect(networkManager, &QNetworkAccessManager::finished,
240         this, &JiraAgent::ticketReceived);
241
242     networkManager->get(request);
243 }
244
245 void JiraAgent::ticketReceived(QNetworkReply *reply)
246 {
247     // qDebug() << "JA::ticketReceived";
248
249     killTimer->stop();
250
251     networkManager->disconnect();
252
253     QString r = reply->readAll();
254
255     if (reply->error()) {
256         if (reply->error() == QNetworkReply::AuthenticationRequiredError)
257             QMessageBox::warning(
258                 nullptr, tr("Warning"),
259                 tr("Authentication problem when contacting JIRA"));
260
261         qWarning() << "JiraAgent::ticketRReveived reply error";
262         qWarning() << "Error: " << reply->error();
263         vout << "reply: " << Qt::endl << r << Qt::endl;
264         finishJob();
265         return;
266     }
267
268     QJsonDocument jsdoc;
269     jsdoc = QJsonDocument::fromJson(r.toUtf8());
270     jsobj = jsdoc.object();
271     continueJob();
272 }
273
274 void JiraAgent::timeout() 
275 {
276     qWarning() << "JiraAgent timeout!!   jobType = " << jobType;
277 }
278
279 #ifndef QT_NO_SSL
280 void JiraAgent::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
281 {
282     QString errorString;
283     foreach (const QSslError &error, errors) {
284         if (!errorString.isEmpty())
285             errorString += '\n';
286         errorString += error.errorString();
287     }
288
289     reply->ignoreSslErrors();
290     qWarning() << "JiraAgent: One or more SSL errors has occurred: " << errorString;
291     qWarning() << "Errors ignored.";
292 }
293 #endif