From 64835283997d13a3035c5f8407cf5009d550405b Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 31 Mar 2014 12:13:38 -0400 Subject: [PATCH] Pull a bunch of code out of HatchetAccount and into HatchetHelpers; make some things more modular; prepare for the Kiva/Dreamcatcher split --- src/accounts/hatchet/CMakeLists.txt | 2 + src/accounts/hatchet/HatchetHelpers.cpp | 233 ++++++++++++++++ src/accounts/hatchet/HatchetHelpers.h | 80 ++++++ .../hatchet/account/HatchetAccount.cpp | 256 +++++------------- src/accounts/hatchet/account/HatchetAccount.h | 31 ++- .../hatchet/account/HatchetAccountConfig.cpp | 1 + .../hatchet/account/HatchetAccountConfig.h | 2 + src/accounts/hatchet/sip/HatchetSip.cpp | 24 +- src/accounts/hatchet/sip/HatchetSip.h | 17 +- .../hatchet/sip/WebSocketThreadController.cpp | 1 - 10 files changed, 435 insertions(+), 212 deletions(-) create mode 100644 src/accounts/hatchet/HatchetHelpers.cpp create mode 100644 src/accounts/hatchet/HatchetHelpers.h diff --git a/src/accounts/hatchet/CMakeLists.txt b/src/accounts/hatchet/CMakeLists.txt index eb082ffa5..9cd9739b0 100644 --- a/src/accounts/hatchet/CMakeLists.txt +++ b/src/accounts/hatchet/CMakeLists.txt @@ -37,11 +37,13 @@ tomahawk_add_plugin(hatchet TYPE account EXPORT_MACRO ACCOUNTDLLEXPORT_PRO SOURCES + HatchetHelpers.cpp account/HatchetAccount.cpp account/HatchetAccountConfig.cpp sip/WebSocket.cpp sip/WebSocketThreadController.cpp sip/HatchetSip.cpp + #sip/HatchetCredentialFetcher.cpp UI account/HatchetAccountConfig.ui LINK_LIBRARIES diff --git a/src/accounts/hatchet/HatchetHelpers.cpp b/src/accounts/hatchet/HatchetHelpers.cpp new file mode 100644 index 000000000..24db2d09d --- /dev/null +++ b/src/accounts/hatchet/HatchetHelpers.cpp @@ -0,0 +1,233 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2014, Jeff Mitchell + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "HatchetHelpers.h" + +#include "utils/Closure.h" +#include "utils/Logger.h" +#include "utils/NetworkAccessManager.h" +#include "utils/TomahawkUtils.h" + +#include + +#include +#include + + +namespace Tomahawk +{ +namespace Accounts +{ +namespace Hatchet +{ +namespace HatchetHelpers +{ + + +QVariantMap +parseReply( QNetworkReply* reply, bool& okRet ) +{ + QVariantMap resp; + + reply->deleteLater(); + + bool ok; + int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok ); + if ( reply->error() != QNetworkReply::NoError && statusCode < 400 ) + { + tLog() << Q_FUNC_INFO << "Network error in command:" << reply->error() << reply->errorString(); + okRet = false; + return resp; + } + + QJson::Parser p; + QByteArray replyData = reply->readAll(); + resp = p.parse( replyData, &ok ).toMap(); + + if ( !ok ) + { + tLog() << Q_FUNC_INFO << "Error parsing JSON from server" << replyData; + okRet = false; + return resp; + } + + if ( statusCode >= 400 ) + { + tDebug() << "Error from tomahawk server response, or in parsing from json:" << resp.value( "error" ).toString() << resp; + } + + tDebug() << Q_FUNC_INFO << "Got keys" << resp.keys(); + tDebug() << Q_FUNC_INFO << "Got values" << resp.values(); + okRet = true; + return resp; +} + + +HatchetCredentialFetcher::HatchetCredentialFetcher( QObject* parent ) + : QObject( parent ) +{ +} + + +HatchetCredentialFetcher::~HatchetCredentialFetcher() +{ + +} + + +void +HatchetCredentialFetcher::fetchAccessToken( const QString& type, const MandellaInformation& mandellaInformation ) +{ + if ( mandellaInformation.bearerToken.isEmpty() || + (mandellaInformation.bearerTokenExpiration < QDateTime::currentDateTime().toTime_t() && + (mandellaInformation.refreshToken.isEmpty() || + (mandellaInformation.refreshTokenExpiration != 0 && mandellaInformation.refreshTokenExpiration < QDateTime::currentDateTime().toTime_t()))) ) + { + tLog() << "No valid combination of access/refresh tokens, not logging in"; + tLog() << "Mandella access token expiration:" << mandellaInformation.bearerTokenExpiration << ", refresh token expiration:" << mandellaInformation.refreshTokenExpiration; + emit authError( "No valid credentials are stored locally, please log in again.", 401, QVariantMap() ); + return; + } + + bool interceptionNeeded = mandellaInformation.bearerTokenExpiration < QDateTime::currentDateTime().toTime_t(); + + QNetworkRequest req( QUrl( "https://auth.hatchet.is/v1/tokens/" + (interceptionNeeded ? "refresh/" + QString::fromUtf8(mandellaInformation.bearerTokenType).toLower() : "fetch/" + type) ) ); + QNetworkReply* reply; + + if ( interceptionNeeded ) + { + tLog() << "Intercepting; new mandella access token needed"; + req.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" ); + QUrl params; + TomahawkUtils::urlAddQueryItem( params, "grant_type", "refresh_token" ); + TomahawkUtils::urlAddQueryItem( params, "refresh_token", mandellaInformation.refreshToken ); + QByteArray data = TomahawkUtils::encodedQuery( params ); + reply = Tomahawk::Utils::nam()->post( req, data ); + reply->setProperty( "originalType", type ); + } + else + { + tLog() << "Fetching token of type" << type; + req.setRawHeader( "Authorization", QString( mandellaInformation.bearerTokenType + " " + mandellaInformation.bearerToken).toUtf8() ); + reply = Tomahawk::Utils::nam()->get( req ); + } + + NewClosure( reply, SIGNAL( finished() ), this, SLOT( onFetchAccessTokenFinished( QNetworkReply*, const QString& ) ), reply, type ); +} + + +void +HatchetCredentialFetcher::onFetchAccessTokenFinished( QNetworkReply* reply, const QString& type ) +{ + tLog() << Q_FUNC_INFO; + Q_ASSERT( reply ); + + QString originalType; + if ( reply->property( "originalType" ).isValid() ) + { + originalType = reply->property( "originalType" ).toString(); + } + + bool ok; + int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok ); + if ( !ok ) + { + tLog() << Q_FUNC_INFO << "Error finding status code from auth server"; + emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() ); + return; + } + const QVariantMap resp = parseReply( reply, ok ); + if ( !ok ) + { + tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server"; + emit authError( "An error occurred reading the reply from the authentication server", statusCode, resp ); + return; + } + if ( statusCode >= 500 ) + { + tLog() << Q_FUNC_INFO << "Encountered internal error from auth server, cannot continue"; + emit authError( "The authentication server reported an internal error, please try again later", statusCode, resp ); + return; + } + if ( statusCode >= 400 ) + { + QString errString = resp.value( "error_description" ).toString(); + tLog() << Q_FUNC_INFO << "An error was returned from the authentication server: " << errString; + emit authError( errString, statusCode, resp ); + return; + } + + if ( !originalType.isEmpty() ) + { + const QByteArray bearerTokenBytes = resp.value( "access_token" ).toByteArray(); + uint bearerTokenExpiration = resp.value( "expires_in" ).toUInt( &ok ); + if ( bearerTokenBytes.isEmpty() || !ok ) + { + tLog() << Q_FUNC_INFO << "Error reading access token or its expiration"; + emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); + return; + } + const QByteArray bearerTokenTypeBytes = resp.value( "token_type" ).toByteArray(); + if ( bearerTokenTypeBytes.isEmpty() ) + { + tLog() << Q_FUNC_INFO << "Error reading access token type"; + emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); + return; + } + + MandellaInformation newMandellaInformation; + newMandellaInformation.bearerTokenType = bearerTokenTypeBytes; + newMandellaInformation.bearerToken = bearerTokenBytes; + newMandellaInformation.bearerTokenExpiration = QDateTime::currentDateTime().toTime_t() + bearerTokenExpiration; + emit mandellaInformationUpdated( newMandellaInformation ); + + fetchAccessToken( originalType, newMandellaInformation ); + return; + } + + const QByteArray accessTokenBytes = resp.value( "access_token" ).toByteArray(); + uint accessTokenExpiration = resp.value( "expires_in" ).toUInt( &ok ); + if ( accessTokenBytes.isEmpty() || !ok ) + { + tLog() << Q_FUNC_INFO << "Error reading access token or its expiration"; + emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); + return; + } + const QByteArray tokenTypeBytes = resp.value( "token_type" ).toByteArray(); + if ( tokenTypeBytes.isEmpty() ) + { + tLog() << Q_FUNC_INFO << "Error reading access token type"; + emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); + return; + } + + tLog() << Q_FUNC_INFO << "Access tokens fetched successfully"; + + AccessTokenInformation accessTokenInformation; + accessTokenInformation.type = tokenTypeBytes; + accessTokenInformation.token = accessTokenBytes; + accessTokenInformation.expiration = accessTokenExpiration; + + emit accessTokenFetched( accessTokenInformation ); +} + + +} +} +} +} diff --git a/src/accounts/hatchet/HatchetHelpers.h b/src/accounts/hatchet/HatchetHelpers.h new file mode 100644 index 000000000..d085c6ed8 --- /dev/null +++ b/src/accounts/hatchet/HatchetHelpers.h @@ -0,0 +1,80 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2014, Jeff Mitchell + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef HATCHET_HELPERS_H +#define HATCHET_HELPERS_H + +#include + +class QNetworkReply; + +namespace Tomahawk +{ +namespace Accounts +{ +namespace Hatchet +{ +namespace HatchetHelpers +{ + + +QVariantMap parseReply( QNetworkReply* reply, bool& ok ); + + +struct MandellaInformation { + QByteArray bearerTokenType; + QByteArray bearerToken; + uint bearerTokenExpiration; + QByteArray refreshToken; + uint refreshTokenExpiration; +}; + +struct AccessTokenInformation { + QByteArray type; + QByteArray token; + uint expiration; +}; + + +class HatchetCredentialFetcher : public QObject +{ + Q_OBJECT + +public: + HatchetCredentialFetcher( QObject* parent ); + virtual ~HatchetCredentialFetcher(); + +signals: + void accessTokenFetched( const HatchetHelpers::AccessTokenInformation& accessInfo ); + void mandellaInformationUpdated( const HatchetHelpers::MandellaInformation& updatedInfo ); + void authError( const QString& error, int statusCode, const QVariantMap& resp ); + +public slots: + void fetchAccessToken( const QString& type, const HatchetHelpers::MandellaInformation& mandellaInformation ); + +private slots: + void onFetchAccessTokenFinished( QNetworkReply*, const QString& type ); +}; + + +} +} +} +} + +#endif diff --git a/src/accounts/hatchet/account/HatchetAccount.cpp b/src/accounts/hatchet/account/HatchetAccount.cpp index 894958d9c..795f9107a 100644 --- a/src/accounts/hatchet/account/HatchetAccount.cpp +++ b/src/accounts/hatchet/account/HatchetAccount.cpp @@ -17,8 +17,8 @@ */ #include "HatchetAccount.h" -#include +#include "HatchetHelpers.h" #include "HatchetAccountConfig.h" #include "sip/HatchetSip.h" #include "utils/Closure.h" @@ -27,16 +27,24 @@ #include "utils/Json.h" #include "utils/TomahawkUtils.h" -#include +#include #include #include #include #include #include #include +#include -using namespace Tomahawk; -using namespace Accounts; +#include +#include + +namespace Tomahawk +{ +namespace Accounts +{ +namespace Hatchet +{ static QPixmap* s_icon = 0; HatchetAccount* HatchetAccount::s_instance = 0; @@ -53,7 +61,6 @@ HatchetAccountFactory::HatchetAccountFactory() HatchetAccountFactory::~HatchetAccountFactory() { - } @@ -223,14 +230,14 @@ HatchetAccount::refreshTokenExpiration() const QByteArray -HatchetAccount::mandellaAccessToken() const +HatchetAccount::bearerToken() const { return credentials().value( "mandella_access_token" ).toByteArray(); } uint -HatchetAccount::mandellaAccessTokenExpiration() const +HatchetAccount::bearerTokenExpiration() const { bool ok; return credentials().value( "mandella_access_token_expiration" ).toUInt( &ok ); @@ -238,7 +245,7 @@ HatchetAccount::mandellaAccessTokenExpiration() const QByteArray -HatchetAccount::mandellaTokenType() const +HatchetAccount::bearerTokenType() const { return credentials().value( "mandella_token_type" ).toByteArray(); } @@ -279,68 +286,14 @@ HatchetAccount::loginWithPassword( const QString& username, const QString& passw } -void -HatchetAccount::fetchAccessToken( const QString& type ) -{ - if ( username().isEmpty() ) - { - tLog() << "No username, not logging in"; - return; - } - if ( mandellaAccessToken().isEmpty() || - (mandellaAccessTokenExpiration() < QDateTime::currentDateTime().toTime_t() && - (refreshToken().isEmpty() || - (refreshTokenExpiration() != 0 && refreshTokenExpiration() < QDateTime::currentDateTime().toTime_t()))) ) - { - tLog() << "No valid combination of access/refresh tokens, not logging in"; - tLog() << "Mandella access token expiration:" << mandellaAccessTokenExpiration() << ", refresh token expiration:" << refreshTokenExpiration(); - emit authError( "No valid credentials are stored locally, please log in again.", 401, QVariantMap() ); - return; - } - - uint matExpiration = mandellaAccessTokenExpiration(); - bool interceptionNeeded = false; - - if ( matExpiration < QDateTime::currentDateTime().toTime_t() ) - { - interceptionNeeded = true; - tLog() << "Mandella access token has expired, fetching new ones first"; - } - else - { - tLog() << "Fetching access tokens of type" << type; - } - - QNetworkRequest req( QUrl( c_accessTokenServer + "/tokens/" + (interceptionNeeded ? "refresh/" + QString::fromUtf8(mandellaTokenType()).toLower() : "fetch/" + type) ) ); - QNetworkReply* reply; - - if ( interceptionNeeded ) - { - tLog() << "Intercepting; new mandella access token needed"; - req.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" ); - QUrl params; - TomahawkUtils::urlAddQueryItem( params, "grant_type", "refresh_token" ); - TomahawkUtils::urlAddQueryItem( params, "refresh_token", refreshToken() ); - QByteArray data = TomahawkUtils::encodedQuery( params ); - reply = Tomahawk::Utils::nam()->post( req, data ); - reply->setProperty( "originalType", type ); - } - else - { - tLog() << "Fetching token of type" << type; - req.setRawHeader( "Authorization", QString( mandellaTokenType() + " " + mandellaAccessToken()).toUtf8() ); - reply = Tomahawk::Utils::nam()->get( req ); - } - - NewClosure( reply, SIGNAL( finished() ), this, SLOT( onFetchAccessTokenFinished( QNetworkReply*, const QString& ) ), reply, type ); -} - - void HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& username ) { tLog() << Q_FUNC_INFO; Q_ASSERT( reply ); + + reply->deleteLater(); + bool ok; int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok ); if ( !ok ) @@ -349,7 +302,7 @@ HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& us emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() ); return; } - const QVariantMap resp = parseReply( reply, ok ); + const QVariantMap resp = HatchetHelpers::parseReply( reply, ok ); if ( !ok ) { tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server"; @@ -420,139 +373,64 @@ HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& us void -HatchetAccount::onFetchAccessTokenFinished( QNetworkReply* reply, const QString& type ) +HatchetAccount::fetchAccessToken( const QString& type ) { - tLog() << Q_FUNC_INFO; - Q_ASSERT( reply ); + QVariantHash creds = credentials(); + HatchetHelpers::MandellaInformation mandellaInfo; + mandellaInfo.bearerToken = bearerToken(); + mandellaInfo.bearerTokenExpiration = bearerTokenExpiration(); + mandellaInfo.bearerTokenType = bearerTokenType(); + mandellaInfo.refreshToken = refreshToken(); + mandellaInfo.refreshTokenExpiration = refreshTokenExpiration(); - QString originalType; - if ( reply->property( "originalType" ).isValid() ) - { - originalType = reply->property( "originalType" ).toString(); - } + HatchetHelpers::HatchetCredentialFetcher* fetcher = new HatchetHelpers::HatchetCredentialFetcher( this ); + connect( fetcher, + SIGNAL( mandellaInformationUpdated( const HatchetHelpers::MandellaInformation& ) ), + SLOT( onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& ) ) ); + connect( fetcher, + SIGNAL( authError( const QString&, int, const QVariantMap& ) ), + SLOT( onFetcherAuthError( const QString&, int, const QVariantMap& ) ) ); + connect( fetcher, + SIGNAL( accessTokenFetched( const HatchetHelpers::AccessTokenInformation& ) ), + SLOT( onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& ) ) ); - bool ok; - int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok ); - if ( !ok ) - { - tLog() << Q_FUNC_INFO << "Error finding status code from auth server"; - emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() ); - return; - } - const QVariantMap resp = parseReply( reply, ok ); - if ( !ok ) - { - tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server"; - emit authError( "An error occurred reading the reply from the authentication server", statusCode, resp ); - return; - } - if ( statusCode >= 500 ) - { - tLog() << Q_FUNC_INFO << "Encountered internal error from auth server, cannot continue"; - emit authError( "The authentication server reported an internal error, please try again later", statusCode, resp ); - return; - } - if ( statusCode >= 400 ) - { - QString errString = resp.value( "error_description" ).toString(); - tLog() << Q_FUNC_INFO << "An error was returned from the authentication server: " << errString; - emit authError( errString, statusCode, resp ); - return; - } + fetcher->fetchAccessToken( type, mandellaInfo ); +} - QVariantMap creds = credentials(); - - if ( !originalType.isEmpty() ) - { - const QByteArray accessTokenBytes = resp.value( "access_token" ).toByteArray(); - uint accessTokenExpiration = resp.value( "expires_in" ).toUInt( &ok ); - if ( accessTokenBytes.isEmpty() || !ok ) - { - tLog() << Q_FUNC_INFO << "Error reading access token or its expiration"; - emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); - return; - } - const QByteArray tokenTypeBytes = resp.value( "token_type" ).toByteArray(); - if ( tokenTypeBytes.isEmpty() ) - { - tLog() << Q_FUNC_INFO << "Error reading access token type"; - emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); - return; - } - creds[ "mandella_access_token" ] = accessTokenBytes; - creds[ "mandella_access_token_expiration" ] = QDateTime::currentDateTime().toTime_t() + accessTokenExpiration; - creds[ "mandella_token_type" ] = tokenTypeBytes; - setCredentials( creds ); - syncConfig(); - - fetchAccessToken( originalType ); - return; - } - - const QByteArray accessTokenBytes = resp.value( "access_token" ).toByteArray(); - uint accessTokenExpiration = resp.value( "expires_in" ).toUInt( &ok ); - if ( accessTokenBytes.isEmpty() || !ok ) - { - tLog() << Q_FUNC_INFO << "Error reading access token or its expiration"; - emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); - return; - } - const QByteArray tokenTypeBytes = resp.value( "token_type" ).toByteArray(); - if ( tokenTypeBytes.isEmpty() ) - { - tLog() << Q_FUNC_INFO << "Error reading access token type"; - emit authError( "An error encountered parsing the authentication server's response", 0, QVariantMap() ); - return; - } - - creds[ type + "_access_token" ] = accessTokenBytes; - - tDebug() << Q_FUNC_INFO << "Creds: " << creds; +void +HatchetAccount::onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& mandellaInformation ) +{ + QVariantHash creds = credentials(); + creds[ "mandella_access_token" ] = mandellaInformation.bearerToken; + creds[ "mandella_access_token_expiration" ] = QDateTime::currentDateTime().toTime_t() + mandellaInformation.bearerTokenExpiration; + creds[ "mandella_token_type" ] = mandellaInformation.bearerTokenType; setCredentials( creds ); syncConfig(); - - tLog() << Q_FUNC_INFO << "Access tokens fetched successfully"; - - emit accessTokenFetched(); } -QVariantMap -HatchetAccount::parseReply( QNetworkReply* reply, bool& okRet ) const +void +HatchetAccount::onFetcherAuthError( const QString& error, int code, const QVariantMap& resp ) { - QVariantMap resp; - - reply->deleteLater(); - - bool ok; - int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok ); - if ( reply->error() != QNetworkReply::NoError && statusCode < 400 ) - { - tLog() << Q_FUNC_INFO << "Network error in command:" << reply->error() << reply->errorString(); - okRet = false; - return resp; - } - - QByteArray replyData = reply->readAll(); - resp = TomahawkUtils::parseJson( replyData, &ok ).toMap(); - - if ( !ok ) - { - tLog() << Q_FUNC_INFO << "Error parsing JSON from server" << replyData; - okRet = false; - return resp; - } - - if ( statusCode >= 400 ) - { - tDebug() << "Error from tomahawk server response, or in parsing from json:" << resp.value( "error" ).toString() << resp; - } - - tDebug() << Q_FUNC_INFO << "Got keys" << resp.keys(); - tDebug() << Q_FUNC_INFO << "Got values" << resp.values(); - okRet = true; - return resp; + if ( sender() ) + sender()->deleteLater(); + emit authError( error, code, resp ); } -Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::HatchetAccountFactory ) + +void +HatchetAccount::onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& accessTokenInfo ) +{ + if ( sender() ) + sender()->deleteLater(); + emit accessTokenFetched( accessTokenInfo ); +} + + +} +} +} + + +Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::Hatchet::HatchetAccountFactory ) diff --git a/src/accounts/hatchet/account/HatchetAccount.h b/src/accounts/hatchet/account/HatchetAccount.h index 92b113b81..226e2a815 100644 --- a/src/accounts/hatchet/account/HatchetAccount.h +++ b/src/accounts/hatchet/account/HatchetAccount.h @@ -20,6 +20,8 @@ #define HATCHET_ACCOUNT_H #include "TomahawkPlugin.h" +#include "HatchetHelpers.h" + #include #include @@ -27,14 +29,15 @@ class QNetworkReply; -class HatchetSipPlugin; - namespace Tomahawk { namespace Accounts { +namespace Hatchet +{ class HatchetAccountConfig; +class HatchetSipPlugin; class ACCOUNTDLLEXPORT HatchetAccountFactory : public AccountFactory { @@ -87,30 +90,31 @@ public: QString username() const; - void fetchAccessToken( const QString& type = "dreamcatcher" ); - signals: - void authError( QString error, int statusCode, const QVariantMap ); + void authError( const QString&, int, const QVariantMap&); void deauthenticated(); - void accessTokenFetched(); + void accessTokenFetched( const HatchetHelpers::AccessTokenInformation& ); + +public slots: + void fetchAccessToken( const QString& type ); private slots: - void onPasswordLoginFinished( QNetworkReply*, const QString& username ); - void onFetchAccessTokenFinished( QNetworkReply*, const QString& type ); + void onPasswordLoginFinished( QNetworkReply*, const QString& ); + void onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& ); + void onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& ); + void onFetcherAuthError( const QString&, int, const QVariantMap& ); private: QByteArray refreshToken() const; uint refreshTokenExpiration() const; - QByteArray mandellaAccessToken() const; - uint mandellaAccessTokenExpiration() const; + QByteArray bearerToken() const; + uint bearerTokenExpiration() const; - QByteArray mandellaTokenType() const; + QByteArray bearerTokenType() const; void loginWithPassword( const QString& username, const QString& password, const QString &otp ); - QVariantMap parseReply( QNetworkReply* reply, bool& ok ) const; - QPointer m_configWidget; Account::ConnectionState m_state; @@ -126,6 +130,7 @@ private: } } +} #endif diff --git a/src/accounts/hatchet/account/HatchetAccountConfig.cpp b/src/accounts/hatchet/account/HatchetAccountConfig.cpp index f0b626762..48e2304d6 100644 --- a/src/accounts/hatchet/account/HatchetAccountConfig.cpp +++ b/src/accounts/hatchet/account/HatchetAccountConfig.cpp @@ -27,6 +27,7 @@ using namespace Tomahawk; using namespace Accounts; +using namespace Hatchet; namespace { enum ButtonAction { diff --git a/src/accounts/hatchet/account/HatchetAccountConfig.h b/src/accounts/hatchet/account/HatchetAccountConfig.h index 55a4f89b7..8af3d00a7 100644 --- a/src/accounts/hatchet/account/HatchetAccountConfig.h +++ b/src/accounts/hatchet/account/HatchetAccountConfig.h @@ -32,6 +32,7 @@ namespace Ui { namespace Tomahawk { namespace Accounts { +namespace Hatchet { class HatchetAccount; @@ -63,6 +64,7 @@ private: HatchetAccount* m_account; }; +} } } diff --git a/src/accounts/hatchet/sip/HatchetSip.cpp b/src/accounts/hatchet/sip/HatchetSip.cpp index fc47cb9a7..6e36d99be 100644 --- a/src/accounts/hatchet/sip/HatchetSip.cpp +++ b/src/accounts/hatchet/sip/HatchetSip.cpp @@ -37,6 +37,14 @@ #include #include +namespace Tomahawk +{ +namespace Accounts +{ +namespace Hatchet +{ + + HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account ) : SipPlugin( account ) , m_sipState( Closed ) @@ -46,7 +54,9 @@ HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account ) { tLog() << Q_FUNC_INFO; - connect( m_account, SIGNAL( accessTokenFetched() ), this, SLOT( connectWebSocket() ) ); + connect( m_account, + SIGNAL( accessTokenFetched( const HatchetHelpers::AccessTokenInformation& ) ), + SLOT( connectWebSocket( const HatchetHelpers::AccessTokenInformation& ) ) ); connect( Servent::instance(), SIGNAL( dbSyncTriggered() ), this, SLOT( dbSyncTriggered() )); /* @@ -95,10 +105,10 @@ HatchetSipPlugin::isValid() const } -Tomahawk::Accounts::HatchetAccount* +HatchetAccount* HatchetSipPlugin::hatchetAccount() const { - return qobject_cast< Tomahawk::Accounts::HatchetAccount* >( m_account ); + return qobject_cast< HatchetAccount* >( m_account ); } @@ -133,7 +143,7 @@ HatchetSipPlugin::disconnectPlugin() void -HatchetSipPlugin::connectWebSocket() +HatchetSipPlugin::connectWebSocket( const HatchetHelpers::AccessTokenInformation& accessTokenInformation ) { tLog() << Q_FUNC_INFO; if ( m_webSocketThreadController ) @@ -157,8 +167,7 @@ HatchetSipPlugin::connectWebSocket() return; } - m_token = m_account->credentials()[ "dreamcatcher_access_token" ].toString(); - + m_token = accessTokenInformation.token; if ( m_token.isEmpty() ) { @@ -585,3 +594,6 @@ HatchetSipPlugin::oplogFetched( const QString& sinceguid, const QString& /* last } +} +} +} diff --git a/src/accounts/hatchet/sip/HatchetSip.h b/src/accounts/hatchet/sip/HatchetSip.h index 426b7f1b6..047babc99 100644 --- a/src/accounts/hatchet/sip/HatchetSip.h +++ b/src/accounts/hatchet/sip/HatchetSip.h @@ -32,6 +32,13 @@ class WebSocketThreadController; const int VERSION = 1; +namespace Tomahawk +{ +namespace Accounts +{ +namespace Hatchet +{ + class ACCOUNTDLLEXPORT HatchetSipPlugin : public SipPlugin { Q_OBJECT @@ -63,14 +70,14 @@ public slots: void webSocketDisconnected(); signals: - void connectWebSocket() const; + void connectWebSocket( const HatchetHelpers::AccessTokenInformation& ) const; void disconnectWebSocket() const; void rawBytes( QByteArray bytes ) const; private slots: void dbSyncTriggered(); void messageReceived( const QByteArray& msg ); - void connectWebSocket(); + void connectWebSocket( const HatchetHelpers::AccessTokenInformation& ); void oplogFetched( const QString& sinceguid, const QString& lastguid, const QList< dbop_ptr > ops ); private: @@ -79,7 +86,7 @@ private: void newPeer( const QVariantMap& valMap ); void peerAuthorization( const QVariantMap& valMap ); void sendOplog( const QVariantMap& valMap ) const; - Tomahawk::Accounts::HatchetAccount* hatchetAccount() const; + HatchetAccount* hatchetAccount() const; QPointer< WebSocketThreadController > m_webSocketThreadController; QString m_token; @@ -91,4 +98,8 @@ private: QHash< QString, QList< SipInfo > > m_sipInfoHash; }; +} +} +} + #endif diff --git a/src/accounts/hatchet/sip/WebSocketThreadController.cpp b/src/accounts/hatchet/sip/WebSocketThreadController.cpp index e0b16960e..dd635346d 100644 --- a/src/accounts/hatchet/sip/WebSocketThreadController.cpp +++ b/src/accounts/hatchet/sip/WebSocketThreadController.cpp @@ -68,7 +68,6 @@ WebSocketThreadController::run() if ( m_webSocket && m_sip ) { tLog() << Q_FUNC_INFO << "Have a valid websocket and parent"; - connect( m_sip, SIGNAL( connectWebSocket() ), m_webSocket, SLOT( connectWs() ), Qt::QueuedConnection ); connect( m_sip, SIGNAL( disconnectWebSocket() ), m_webSocket, SLOT( disconnectWs() ), Qt::QueuedConnection ); connect( m_sip, SIGNAL( rawBytes( QByteArray ) ), m_webSocket, SLOT( encodeMessage( QByteArray ) ), Qt::QueuedConnection ); connect( m_webSocket, SIGNAL( connected() ), m_sip, SLOT( webSocketConnected() ), Qt::QueuedConnection );