diff --git a/tempo/integrationplugintempo.cpp b/tempo/integrationplugintempo.cpp index f4621b0b..e341a80a 100644 --- a/tempo/integrationplugintempo.cpp +++ b/tempo/integrationplugintempo.cpp @@ -49,40 +49,16 @@ void IntegrationPluginTempo::startPairing(ThingPairingInfo *info) if (info->thingClassId() == tempoConnectionThingClassId) { - QByteArray clientId = configValue(tempoPluginCustomClientIdParamTypeId).toByteArray(); - QByteArray clientSecret = configValue(tempoPluginCustomClientSecretParamTypeId).toByteArray(); - if (clientId.isEmpty() || clientSecret.isEmpty()) { - clientId = apiKeyStorage()->requestKey("tempo").data("clientId"); - clientSecret = apiKeyStorage()->requestKey("tempo").data("clientSecret"); - } else { - qCDebug(dcTempo()) << "Using custom client secret and id"; - } - if (clientId.isEmpty() || clientSecret.isEmpty()) { - info->finish(Thing::ThingErrorAuthenticationFailure, tr("Client id and/or seceret is not available.")); - return; - } QString jiraCloudInstanceName = info->params().paramValue(tempoConnectionThingAtlassianAccountNameParamTypeId).toString(); - Tempo *tempo = new Tempo(hardwareManager()->networkManager(), clientId, clientSecret, this); - QUrl url = tempo->getLoginUrl(QUrl("https://127.0.0.1:8888"), jiraCloudInstanceName); qCDebug(dcTempo()) << "Checking if the Tempo server is reachable: https://api.tempo.io/core/3"; QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(QUrl("https://api.tempo.io/core/3"))); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); - connect(reply, &QNetworkReply::finished, info, [reply, info, tempo, url, this] { + connect(reply, &QNetworkReply::finished, info, [reply, info, this] { if (reply->error() != QNetworkReply::NetworkError::HostNotFoundError) { qCDebug(dcTempo()) << "Tempo server is reachable"; - ThingId thingId = info->thingId(); - m_setupTempoConnections.insert(info->thingId(), tempo); - connect(info, &ThingPairingInfo::aborted, this, [thingId, this] { - qCWarning(dcTempo()) << "ThingPairingInfo aborted, cleaning up"; - Tempo *tempo = m_setupTempoConnections.take(thingId); - if (tempo) - tempo->deleteLater(); - }); - qCDebug(dcTempo()) << "OAuthUrl" << url.toString(); - info->setOAuthUrl(url); info->finish(Thing::ThingErrorNoError); } else { qCWarning(dcTempo()) << "Got online check error" << reply->error() << reply->errorString(); @@ -101,36 +77,61 @@ void IntegrationPluginTempo::confirmPairing(ThingPairingInfo *info, const QStrin if (info->thingClassId() == tempoConnectionThingClassId) { qCDebug(dcTempo()) << "Confirm pairing" << info->thingName(); - QUrl url(secret); - QUrlQuery query(url); - QByteArray authorizationCode = query.queryItemValue("code").toLocal8Bit(); - if (authorizationCode.isEmpty()) { + if (secret.isEmpty()) { qCWarning(dcTempo()) << "No authorization code received."; return info->finish(Thing::ThingErrorAuthenticationFailure); } - - Tempo *tempo = m_setupTempoConnections.value(info->thingId()); - if (!tempo) { - qWarning(dcTempo()) << "No tempo connection found for device:" << info->thingName(); - m_setupTempoConnections.remove(info->thingId()); - return info->finish(Thing::ThingErrorHardwareFailure); - } - qCDebug(dcTempo()) << "Authorization code" << authorizationCode.mid(0, 4)+QString().fill('*', authorizationCode.length()-4) ; - tempo->getAccessTokenFromAuthorizationCode(authorizationCode); - connect(tempo, &Tempo::receivedRefreshToken, info, [info, this](const QByteArray &refreshToken){ - qCDebug(dcTempo()) << "Token:" << refreshToken.mid(0, 4)+QString().fill('*', refreshToken.length()-4) ; - - pluginStorage()->beginGroup(info->thingId().toString()); - pluginStorage()->setValue("refresh_token", refreshToken); - pluginStorage()->endGroup(); - - info->finish(Thing::ThingErrorNoError); + QString atlassianAccountName = info->params().paramValue(tempoConnectionThingAtlassianAccountNameParamTypeId).toString(); + Tempo *tempo = new Tempo(hardwareManager()->networkManager(), atlassianAccountName, secret, this); + tempo->getAccounts(); + connect(info, &ThingPairingInfo::aborted, tempo, &Tempo::deleteLater); + connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, this] (bool authenticated){ + if (authenticated) { + m_setupTempoConnections.insert(info->thingId(), tempo); + info->finish(Thing::ThingErrorNoError); + } }); } else { Q_ASSERT_X(false, "confirmPairing", QString("Unhandled thingClassId: %1").arg(info->thingClassId().toString()).toUtf8()); } } +void IntegrationPluginTempo::discoverThings(ThingDiscoveryInfo *info) +{ + qCDebug(dcTempo()) << "Discover things"; + if (info->thingClassId() == accountThingClassId) { + Q_FOREACH(Tempo *tempo, m_tempoConnections) { + tempo->getAccounts(); + Thing *parentThing = m_tempoConnections.key(tempo); + if (!parentThing) { + qCWarning(dcTempo()) << "Parent not found"; + return; + } + connect(tempo, &Tempo::accountsReceived, info, [info, parentThing, this, tempo] (const QList &accounts) { + Q_FOREACH(Tempo::Account account, accounts) { + ThingDescriptor descriptor(accountThingClassId, account.name, account.customer.name, parentThing->id()); + ParamList params; + params << Param(accountThingKeyParamTypeId, account.key); + descriptor.setParams(params); + info->addThingDescriptor(descriptor); + } + }); + } + } else if (info->thingClassId() == teamThingClassId) { + Q_FOREACH(Tempo *tempo, m_tempoConnections) { + tempo->getTeams(); + Thing *parentThing = m_tempoConnections.key(tempo); + if (!parentThing) { + qCWarning(dcTempo()) << "Parent not found"; + return; + } + } + } + QTimer::singleShot(5000, info, [info] { + info->finish(Thing::ThingErrorNoError); + }); +} + void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) { Thing *thing = info->thing(); @@ -155,37 +156,30 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) } else { //device loaded from the device database, needs a new access token; pluginStorage()->beginGroup(thing->id().toString()); - QByteArray refreshToken = pluginStorage()->value("refresh_token").toByteArray(); + QByteArray token = pluginStorage()->value("token").toByteArray(); pluginStorage()->endGroup(); - if (refreshToken.isEmpty()) { - info->finish(Thing::ThingErrorAuthenticationFailure, tr("Refresh token is not available.")); + if (token.isEmpty()) { + info->finish(Thing::ThingErrorAuthenticationFailure, tr("Token is not available.")); return; } + QString jiraInstanceName = thing->paramValue(tempoConnectionThingAtlassianAccountNameParamTypeId).toString(); + Tempo *tempo = new Tempo(hardwareManager()->networkManager(), jiraInstanceName, token, this); + tempo->getAccounts(); - QByteArray clientId = configValue(tempoPluginCustomClientIdParamTypeId).toByteArray(); - QByteArray clientSecret = configValue(tempoPluginCustomClientSecretParamTypeId).toByteArray(); - if (clientId.isEmpty() || clientSecret.isEmpty()) { - clientId = apiKeyStorage()->requestKey("tempo").data("clientId"); - clientSecret = apiKeyStorage()->requestKey("tempo").data("clientSecret"); - } else { - qCDebug(dcTempo()) << "Using custom API id and secret."; - } - if (clientId.isEmpty() || clientSecret.isEmpty()) { - info->finish(Thing::ThingErrorAuthenticationFailure, tr("Client id and/or secret is not available.")); - return; - } - Tempo *tempo = new Tempo(hardwareManager()->networkManager(), clientId, clientSecret, this); - tempo->getAccessTokenFromRefreshToken(refreshToken); - connect(tempo, &Tempo::receivedAccessToken, info, [info] { - info->finish(Thing::ThingErrorNoError); - }); connect(info, &ThingSetupInfo::aborted, tempo, &Tempo::deleteLater); + connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, this] (bool authenticated){ + if (authenticated) { + m_tempoConnections.insert(info->thing(), tempo); + info->finish(Thing::ThingErrorNoError); + } + }); } connect(tempo, &Tempo::connectionChanged, this, &IntegrationPluginTempo::onConnectionChanged); connect(tempo, &Tempo::authenticationStatusChanged, this, &IntegrationPluginTempo::onAuthenticationStatusChanged); connect(tempo, &Tempo::accountsReceived, this, &IntegrationPluginTempo::onReceivedAccounts); - } else if (thing->thingClassId() == accountThingClassId) { + } else if (thing->thingClassId() == accountThingClassId || + thing->thingClassId() == teamThingClassId){ Thing *parentThing = myThings().findById(thing->parentId()); if (parentThing->setupComplete()) { info->finish(Thing::ThingErrorNoError); @@ -231,6 +225,8 @@ void IntegrationPluginTempo::postSetupThing(Thing *thing) } else if (thing->thingClassId() == accountThingClassId) { + } else if (thing->thingClassId() == teamThingClassId) { + } } @@ -276,46 +272,12 @@ void IntegrationPluginTempo::onAuthenticationStatusChanged(bool authenticated) return; thing->setStateValue(tempoConnectionLoggedInStateTypeId, authenticated); - if (!authenticated) { - //refresh access token needs to be refreshed - pluginStorage()->beginGroup(thing->id().toString()); - QByteArray refreshToken = pluginStorage()->value("refresh_token").toByteArray(); - pluginStorage()->endGroup(); - tempoConnection->getAccessTokenFromRefreshToken(refreshToken); - } } void IntegrationPluginTempo::onReceivedAccounts(const QList &accounts) { qCDebug(dcTempo()) << "Received" << accounts.count() << "accounts"; - - Tempo *tempoConnection = static_cast(sender()); - Thing *parentThing = m_tempoConnections.key(tempoConnection); - if (!parentThing) - return; - - ThingDescriptors desciptors; - Q_FOREACH(Tempo::Account account, accounts) { - ThingClassId thingClassId; - - //Thing * existingThing = myThings().findByParams(ParamList() << Param(m_idParamTypeIds.value(thingClassId), appliance.homeApplianceId)); - //if (existingThing) { - // qCDebug(dcTempo()) << "Thing is already added to system" << existingThing->name(); - //Set connected state; - //existingThing->setStateValue(m_connectedStateTypeIds.value(thingClassId), appliance.connected); - // continue; - // } - qCDebug(dcTempo()) << "Found new account:" << account.name << "key:" << account.key << "id:" << account.id; - ThingDescriptor descriptor(thingClassId, account.name, account.key, parentThing->id()); - - ParamList params; - //params << Param(m_idParamTypeIds.value(thingClassId), appliance.homeApplianceId); - descriptor.setParams(params); - desciptors.append(descriptor); - } - if (!desciptors.isEmpty()) - emit autoThingsAppeared(desciptors); } void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &accountKey, QList workloads) diff --git a/tempo/integrationplugintempo.h b/tempo/integrationplugintempo.h index 4139452e..b1ee298c 100644 --- a/tempo/integrationplugintempo.h +++ b/tempo/integrationplugintempo.h @@ -49,6 +49,7 @@ public: void startPairing(ThingPairingInfo *info) override; void confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret) override; + void discoverThings(ThingDiscoveryInfo *info) override; void setupThing(ThingSetupInfo *info) override; void postSetupThing(Thing *thing) override; void executeAction(ThingActionInfo *info) override; diff --git a/tempo/integrationplugintempo.json b/tempo/integrationplugintempo.json index c20b4cc7..349b00d4 100644 --- a/tempo/integrationplugintempo.json +++ b/tempo/integrationplugintempo.json @@ -2,23 +2,6 @@ "id": "809bc4ca-d1cd-4279-9e0d-7324537ccb5a", "name": "tempo", "displayName": "Tempo", - "apiKeys": ["tempo"], - "paramTypes": [ - { - "id": "c130b2b7-6d30-406e-899b-669a065daee3", - "name": "customClientId", - "displayName": "Custom client id", - "defaultValue": "", - "type": "QString" - }, - { - "id": "9c759711-e772-44ce-9d86-6a3af89c2d94", - "name": "customClientSecret", - "displayName": "Custom client secret", - "defaultValue": "", - "type": "QString" - } - ], "vendors": [ { "id": "58fc1ab7-b8b5-4e52-8388-72957ce5852d", @@ -31,7 +14,7 @@ "displayName": "Tempo connection", "interfaces": ["account"], "createMethods": ["user"], - "setupMethod": "oauth", + "setupMethod": "displayPin", "paramTypes": [ { "id": "b4110c37-8331-4057-8e9f-12f34c2623fe", @@ -82,7 +65,7 @@ "name": "account", "displayName": "Account", "interfaces": ["connectable"], - "createMethods": ["auto"], + "createMethods": ["discovery"], "browsable": true, "paramTypes": [ { @@ -183,6 +166,34 @@ "unit": "Minutes" } ] + }, + { + "id": "11c85176-e7fe-44b4-995a-24757273f3af", + "name": "team", + "displayName": "Team", + "interfaces": ["connectable"], + "createMethods": ["discovery"], + "browsable": true, + "paramTypes": [ + { + "id": "bb90e986-fcfa-47e8-8783-f2b5a887314a", + "name": "key", + "displayName": "Key", + "defaultValue": "", + "type": "QString" + } + ], + "stateTypes": [ + { + "id": "a125d3b5-676f-49eb-bb93-feae233c2e91", + "name": "connected", + "displayName": "Connected", + "displayNameEvent": "Connected changed", + "defaultValue": true, + "cached": false, + "type": "bool" + } + ] } ] } diff --git a/tempo/tempo.cpp b/tempo/tempo.cpp index adc5af28..7f042070 100644 --- a/tempo/tempo.cpp +++ b/tempo/tempo.cpp @@ -34,158 +34,61 @@ #include "tempo.h" #include "extern-plugininfo.h" -Tempo::Tempo(NetworkAccessManager *networkmanager, const QByteArray &clientId, const QByteArray &clientSecret, QObject *parent) : +Tempo::Tempo(NetworkAccessManager *networkmanager, const QString &jiraCloudInstanceName, const QString &token, QObject *parent) : QObject(parent), - m_clientId(clientId), - m_clientSecret(clientSecret), + m_token(token), + m_jiraCloudInstanceName(jiraCloudInstanceName), m_networkManager(networkmanager) - { - m_tokenRefreshTimer = new QTimer(this); - m_tokenRefreshTimer->setSingleShot(true); - connect(m_tokenRefreshTimer, &QTimer::timeout, this, &Tempo::onRefreshTimer); + qCDebug(dcTempo()) << "Creating tempo connection to" << m_jiraCloudInstanceName; } -QByteArray Tempo::accessToken() +Tempo::~Tempo() { - return m_accessToken; + qCDebug(dcTempo()) << "Deleting tempo connection to" << m_jiraCloudInstanceName; } -QByteArray Tempo::refreshToken() +QString Tempo::token() const { - return m_refreshToken; + return m_token; } -QUrl Tempo::getLoginUrl(const QUrl &redirectUrl, const QString &jiraCloudInstanceName) +void Tempo::getTeams() { - if (m_clientId.isEmpty()) { - qWarning(dcTempo) << "Client Id not defined!"; - return QUrl(""); - } - - if (redirectUrl.isEmpty()){ - qWarning(dcTempo) << "No redirect uri defined!"; - } - m_redirectUri = QUrl::toPercentEncoding(redirectUrl.toString()); - - QUrl url; - url.setScheme("https"); - url.setHost(jiraCloudInstanceName+".atlassian.net"); - url.setPath("/plugins/servlet/ac/io.tempo.jira/oauth-authorize/"); - QUrlQuery query; - query.addQueryItem("client_id", m_clientId); - query.addQueryItem("redirect_uri", m_redirectUri); - query.addQueryItem("access_type", "tenant_user"); - url.setQuery(query); - return url; -} - -void Tempo::getAccessTokenFromRefreshToken(const QByteArray &refreshToken) -{ - if (refreshToken.isEmpty()) { - qWarning(dcTempo) << "No refresh token given!"; - setAuthenticated(false); - return; - } - - QUrl url(m_baseTokenUrl); - QUrlQuery query; - query.clear(); - query.addQueryItem("grant_type", "refresh_token"); - query.addQueryItem("refresh_token", refreshToken); - query.addQueryItem("client_secret", m_clientSecret); + QUrl url = QUrl(m_baseControlUrl+"/teams"); + qCDebug(dcTempo()) << "Get teams, url" << url.toString(); QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + request.setRawHeader("Authorization", "Bearer "+m_token.toUtf8()); - QNetworkReply *reply = m_networkManager->post(request, query.toString().toUtf8()); + QNetworkReply *reply = m_networkManager->get(request); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); - connect(reply, &QNetworkReply::finished, this, [this, reply](){ + connect(reply, &QNetworkReply::finished, this, [this, reply]{ QByteArray rawData = reply->readAll(); if (!checkStatusCode(reply, rawData)) { return; } - QJsonDocument data = QJsonDocument::fromJson(rawData); + QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap(); + QVariantList teamList = dataMap.value("results").toList(); + QList teams; + Q_FOREACH(QVariant var, teamList) { + QVariantMap map = var.toMap(); + Team team; + team.self = map["self"].toString(); + team.id = map["id"].toInt(); + team.name = map["name"].toString(); + team.summary = map["summery"].toString(); - if(!data.toVariant().toMap().contains("access_token")) { - setAuthenticated(false); - return; + QVariantMap lead = map["lead"].toMap(); + team.lead.self = lead["self"].toString(); + team.lead.accountId = lead["accountId"].toString(); + team.lead.displayName = lead["displayName"].toString(); + + teams.append(team); } - m_accessToken = data.toVariant().toMap().value("access_token").toByteArray(); - emit receivedAccessToken(m_accessToken); - - if (data.toVariant().toMap().contains("expires_in")) { - int expireTime = data.toVariant().toMap().value("expires_in").toInt(); - qCDebug(dcTempo) << "Access token expires int" << expireTime << "s, at" << QDateTime::currentDateTime().addSecs(expireTime).toString(); - if (!m_tokenRefreshTimer) { - qWarning(dcTempo()) << "Access token refresh timer not initialized"; - return; - } - if (expireTime < 20) { - qCWarning(dcTempo()) << "Expire time too short"; - return; - } - m_tokenRefreshTimer->start((expireTime - 20) * 1000); - } - }); -} - -void Tempo::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationCode) -{ - // Obtaining access token - if(authorizationCode.isEmpty()) - qWarning(dcTempo()) << "No authorization code given!"; - if(m_clientId.isEmpty()) - qWarning(dcTempo()) << "Client key not set!"; - if(m_clientSecret.isEmpty()) - qWarning(dcTempo()) << "Client secret not set!"; - - QUrl url = QUrl(m_baseTokenUrl); - QUrlQuery query; url.setQuery(query); - - query.clear(); - query.addQueryItem("client_id", m_clientId); - query.addQueryItem("client_secret", m_clientSecret); - query.addQueryItem("redirect_uri", m_redirectUri); - query.addQueryItem("grant_type", "authorization_code"); - query.addQueryItem("code", authorizationCode); - // query.addQueryItem("code_verifier", m_codeChallenge); - - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - - QNetworkReply *reply = m_networkManager->post(request, query.toString().toUtf8()); - connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); - connect(reply, &QNetworkReply::finished, this, [this, reply](){ - - QByteArray rawData = reply->readAll(); - if (!checkStatusCode(reply, rawData)) { - return; - } - QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData); - if(!jsonDoc.toVariant().toMap().contains("access_token") || !jsonDoc.toVariant().toMap().contains("refresh_token") ) { - setAuthenticated(false); - return; - } - m_accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray(); - receivedAccessToken(m_accessToken); - m_refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toByteArray(); - receivedRefreshToken(m_refreshToken); - - if (jsonDoc.toVariant().toMap().contains("expires_in")) { - int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt(); - qCDebug(dcTempo()) << "Token expires in" << expireTime << "s, at" << QDateTime::currentDateTime().addSecs(expireTime).toString(); - if (!m_tokenRefreshTimer) { - qWarning(dcTempo()) << "Token refresh timer not initialized"; - setAuthenticated(false); - return; - } - if (expireTime < 20) { - qCWarning(dcTempo()) << "Expire time too short"; - return; - } - m_tokenRefreshTimer->start((expireTime - 20) * 1000); + if (!teams.isEmpty()) { + emit teamsReceived(teams); } }); } @@ -193,9 +96,10 @@ void Tempo::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC void Tempo::getAccounts() { QUrl url = QUrl(m_baseControlUrl+"/accounts"); + qCDebug(dcTempo()) << "Get accounts. Url" << url.toString(); QNetworkRequest request(url); - request.setRawHeader("Authorization", "Bearer "+m_accessToken); + request.setRawHeader("Authorization", "Bearer "+m_token.toUtf8()); QNetworkReply *reply = m_networkManager->get(request); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); @@ -243,7 +147,7 @@ void Tempo::getAccounts() accounts.append(account); } if (!accounts.isEmpty()) { - + emit accountsReceived(accounts); } }); } @@ -256,8 +160,10 @@ void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to query.addQueryItem("to", to.toString(Qt::DateFormat::ISODate)); url.setQuery(query); + qCDebug(dcTempo()) << "Get workload by account. Url" << url.toString(); + QNetworkRequest request(url); - request.setRawHeader("Authorization", "Bearer "+m_accessToken); + request.setRawHeader("Authorization", "Bearer "+m_token.toUtf8()); QNetworkReply *reply = m_networkManager->get(request); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); @@ -292,12 +198,6 @@ void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to }); } -void Tempo::onRefreshTimer() -{ - qCDebug(dcTempo()) << "Refresh authentication token"; - getAccessTokenFromRefreshToken(m_refreshToken); -} - void Tempo::setAuthenticated(bool state) { if (state != m_authenticated) { diff --git a/tempo/tempo.h b/tempo/tempo.h index 9bfd7d51..1492ec87 100644 --- a/tempo/tempo.h +++ b/tempo/tempo.h @@ -102,31 +102,29 @@ public: QString authorDisplayName; }; - explicit Tempo(NetworkAccessManager *networkmanager, const QByteArray &clientId, const QByteArray &clientSecret, QObject *parent = nullptr); - QByteArray accessToken(); - QByteArray refreshToken(); + struct Team { + QUrl self; + int id; + QString name; + QString summary; + Lead lead; + }; - QUrl getLoginUrl(const QUrl &redirectUrl, const QString &jiraCloudInstanceName); - - void getAccessTokenFromRefreshToken(const QByteArray &refreshToken); - void getAccessTokenFromAuthorizationCode(const QByteArray &authorizationCode); + explicit Tempo(NetworkAccessManager *networkmanager, const QString &jiraCloudInstanceName, const QString &token, QObject *parent = nullptr); + ~Tempo() override; + QString token() const; + void getTeams(); void getAccounts(); void getWorkloadByAccount(const QString &accountKey, QDate from, QDate to); private: - QByteArray m_baseTokenUrl = "https://api.tempo.io/oauth/token/"; QByteArray m_baseControlUrl = "https://api.tempo.io/core/3/"; - QByteArray m_clientId; - QByteArray m_clientSecret; - - QByteArray m_accessToken; - QByteArray m_refreshToken; - QByteArray m_redirectUri = "https://127.0.0.1:8888"; + QString m_token; + QString m_jiraCloudInstanceName; NetworkAccessManager *m_networkManager = nullptr; - QTimer *m_tokenRefreshTimer = nullptr; void setAuthenticated(bool state); void setConnected(bool state); @@ -135,16 +133,15 @@ private: bool m_connected = false; bool checkStatusCode(QNetworkReply *reply, const QByteArray &rawData); + private slots: - void onRefreshTimer(); signals: void authenticationStatusChanged(bool state); void connectionChanged(bool connected); - void receivedRefreshToken(const QByteArray &refreshToken); - void receivedAccessToken(const QByteArray &accessToken); - void accountsReceived(const QList accounts); + void teamsReceived(const QList teams); + void accountsReceived(const QList accounts); void accountWorklogsReceived(const QString &accountKey, QList worklogs); };