1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-14 01:54:07 +02:00

Pull a bunch of code out of HatchetAccount and into HatchetHelpers; make some things more modular; prepare for the Kiva/Dreamcatcher split

This commit is contained in:
Jeff Mitchell
2014-03-31 12:13:38 -04:00
parent 5d1771a710
commit 6483528399
10 changed files with 435 additions and 212 deletions

View File

@@ -37,11 +37,13 @@ tomahawk_add_plugin(hatchet
TYPE account TYPE account
EXPORT_MACRO ACCOUNTDLLEXPORT_PRO EXPORT_MACRO ACCOUNTDLLEXPORT_PRO
SOURCES SOURCES
HatchetHelpers.cpp
account/HatchetAccount.cpp account/HatchetAccount.cpp
account/HatchetAccountConfig.cpp account/HatchetAccountConfig.cpp
sip/WebSocket.cpp sip/WebSocket.cpp
sip/WebSocketThreadController.cpp sip/WebSocketThreadController.cpp
sip/HatchetSip.cpp sip/HatchetSip.cpp
#sip/HatchetCredentialFetcher.cpp
UI UI
account/HatchetAccountConfig.ui account/HatchetAccountConfig.ui
LINK_LIBRARIES LINK_LIBRARIES

View File

@@ -0,0 +1,233 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2014, Jeff Mitchell <jeff@tomahawk-player.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "HatchetHelpers.h"
#include "utils/Closure.h"
#include "utils/Logger.h"
#include "utils/NetworkAccessManager.h"
#include "utils/TomahawkUtils.h"
#include <qjson/parser.h>
#include <QDateTime>
#include <QNetworkReply>
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 );
}
}
}
}
}

View File

@@ -0,0 +1,80 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2014, Jeff Mitchell <jeff@tomahawk-player.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef HATCHET_HELPERS_H
#define HATCHET_HELPERS_H
#include <QVariantMap>
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

View File

@@ -17,8 +17,8 @@
*/ */
#include "HatchetAccount.h" #include "HatchetAccount.h"
#include <QHostInfo>
#include "HatchetHelpers.h"
#include "HatchetAccountConfig.h" #include "HatchetAccountConfig.h"
#include "sip/HatchetSip.h" #include "sip/HatchetSip.h"
#include "utils/Closure.h" #include "utils/Closure.h"
@@ -27,16 +27,24 @@
#include "utils/Json.h" #include "utils/Json.h"
#include "utils/TomahawkUtils.h" #include "utils/TomahawkUtils.h"
#include <QtPlugin> #include <QHostInfo>
#include <QFile> #include <QFile>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QUrl> #include <QUrl>
#include <QUuid> #include <QUuid>
#include <QtPlugin>
using namespace Tomahawk; #include <qjson/parser.h>
using namespace Accounts; #include <qjson/serializer.h>
namespace Tomahawk
{
namespace Accounts
{
namespace Hatchet
{
static QPixmap* s_icon = 0; static QPixmap* s_icon = 0;
HatchetAccount* HatchetAccount::s_instance = 0; HatchetAccount* HatchetAccount::s_instance = 0;
@@ -53,7 +61,6 @@ HatchetAccountFactory::HatchetAccountFactory()
HatchetAccountFactory::~HatchetAccountFactory() HatchetAccountFactory::~HatchetAccountFactory()
{ {
} }
@@ -223,14 +230,14 @@ HatchetAccount::refreshTokenExpiration() const
QByteArray QByteArray
HatchetAccount::mandellaAccessToken() const HatchetAccount::bearerToken() const
{ {
return credentials().value( "mandella_access_token" ).toByteArray(); return credentials().value( "mandella_access_token" ).toByteArray();
} }
uint uint
HatchetAccount::mandellaAccessTokenExpiration() const HatchetAccount::bearerTokenExpiration() const
{ {
bool ok; bool ok;
return credentials().value( "mandella_access_token_expiration" ).toUInt( &ok ); return credentials().value( "mandella_access_token_expiration" ).toUInt( &ok );
@@ -238,7 +245,7 @@ HatchetAccount::mandellaAccessTokenExpiration() const
QByteArray QByteArray
HatchetAccount::mandellaTokenType() const HatchetAccount::bearerTokenType() const
{ {
return credentials().value( "mandella_token_type" ).toByteArray(); 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 void
HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& username ) HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& username )
{ {
tLog() << Q_FUNC_INFO; tLog() << Q_FUNC_INFO;
Q_ASSERT( reply ); Q_ASSERT( reply );
reply->deleteLater();
bool ok; bool ok;
int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok ); int statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt( &ok );
if ( !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() ); emit authError( "An error occurred getting the status code from the server", 0, QVariantMap() );
return; return;
} }
const QVariantMap resp = parseReply( reply, ok ); const QVariantMap resp = HatchetHelpers::parseReply( reply, ok );
if ( !ok ) if ( !ok )
{ {
tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server"; tLog() << Q_FUNC_INFO << "Error getting parsed reply from auth server";
@@ -420,139 +373,64 @@ HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& us
void void
HatchetAccount::onFetchAccessTokenFinished( QNetworkReply* reply, const QString& type ) HatchetAccount::fetchAccessToken( const QString& type )
{ {
tLog() << Q_FUNC_INFO; QVariantHash creds = credentials();
Q_ASSERT( reply ); HatchetHelpers::MandellaInformation mandellaInfo;
mandellaInfo.bearerToken = bearerToken();
mandellaInfo.bearerTokenExpiration = bearerTokenExpiration();
mandellaInfo.bearerTokenType = bearerTokenType();
mandellaInfo.refreshToken = refreshToken();
mandellaInfo.refreshTokenExpiration = refreshTokenExpiration();
QString originalType; HatchetHelpers::HatchetCredentialFetcher* fetcher = new HatchetHelpers::HatchetCredentialFetcher( this );
if ( reply->property( "originalType" ).isValid() ) connect( fetcher,
{ SIGNAL( mandellaInformationUpdated( const HatchetHelpers::MandellaInformation& ) ),
originalType = reply->property( "originalType" ).toString(); 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; fetcher->fetchAccessToken( type, mandellaInfo );
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;
}
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 ); setCredentials( creds );
syncConfig(); syncConfig();
tLog() << Q_FUNC_INFO << "Access tokens fetched successfully";
emit accessTokenFetched();
} }
QVariantMap void
HatchetAccount::parseReply( QNetworkReply* reply, bool& okRet ) const HatchetAccount::onFetcherAuthError( const QString& error, int code, const QVariantMap& resp )
{ {
QVariantMap resp; if ( sender() )
sender()->deleteLater();
reply->deleteLater(); emit authError( error, code, resp );
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;
} }
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 )

View File

@@ -20,6 +20,8 @@
#define HATCHET_ACCOUNT_H #define HATCHET_ACCOUNT_H
#include "TomahawkPlugin.h" #include "TomahawkPlugin.h"
#include "HatchetHelpers.h"
#include <accounts/Account.h> #include <accounts/Account.h>
#include <accounts/AccountDllMacro.h> #include <accounts/AccountDllMacro.h>
@@ -27,14 +29,15 @@
class QNetworkReply; class QNetworkReply;
class HatchetSipPlugin;
namespace Tomahawk namespace Tomahawk
{ {
namespace Accounts namespace Accounts
{ {
namespace Hatchet
{
class HatchetAccountConfig; class HatchetAccountConfig;
class HatchetSipPlugin;
class ACCOUNTDLLEXPORT HatchetAccountFactory : public AccountFactory class ACCOUNTDLLEXPORT HatchetAccountFactory : public AccountFactory
{ {
@@ -87,30 +90,31 @@ public:
QString username() const; QString username() const;
void fetchAccessToken( const QString& type = "dreamcatcher" );
signals: signals:
void authError( QString error, int statusCode, const QVariantMap ); void authError( const QString&, int, const QVariantMap&);
void deauthenticated(); void deauthenticated();
void accessTokenFetched(); void accessTokenFetched( const HatchetHelpers::AccessTokenInformation& );
public slots:
void fetchAccessToken( const QString& type );
private slots: private slots:
void onPasswordLoginFinished( QNetworkReply*, const QString& username ); void onPasswordLoginFinished( QNetworkReply*, const QString& );
void onFetchAccessTokenFinished( QNetworkReply*, const QString& type ); void onFetcherMandellaInformationUpdated( const HatchetHelpers::MandellaInformation& );
void onFetcherAccessTokenFetched( const HatchetHelpers::AccessTokenInformation& );
void onFetcherAuthError( const QString&, int, const QVariantMap& );
private: private:
QByteArray refreshToken() const; QByteArray refreshToken() const;
uint refreshTokenExpiration() const; uint refreshTokenExpiration() const;
QByteArray mandellaAccessToken() const; QByteArray bearerToken() const;
uint mandellaAccessTokenExpiration() const; uint bearerTokenExpiration() const;
QByteArray mandellaTokenType() const; QByteArray bearerTokenType() const;
void loginWithPassword( const QString& username, const QString& password, const QString &otp ); void loginWithPassword( const QString& username, const QString& password, const QString &otp );
QVariantMap parseReply( QNetworkReply* reply, bool& ok ) const;
QPointer<HatchetAccountConfig> m_configWidget; QPointer<HatchetAccountConfig> m_configWidget;
Account::ConnectionState m_state; Account::ConnectionState m_state;
@@ -126,6 +130,7 @@ private:
} }
} }
}
#endif #endif

View File

@@ -27,6 +27,7 @@
using namespace Tomahawk; using namespace Tomahawk;
using namespace Accounts; using namespace Accounts;
using namespace Hatchet;
namespace { namespace {
enum ButtonAction { enum ButtonAction {

View File

@@ -32,6 +32,7 @@ namespace Ui {
namespace Tomahawk { namespace Tomahawk {
namespace Accounts { namespace Accounts {
namespace Hatchet {
class HatchetAccount; class HatchetAccount;
@@ -63,6 +64,7 @@ private:
HatchetAccount* m_account; HatchetAccount* m_account;
}; };
}
} }
} }

View File

@@ -37,6 +37,14 @@
#include <QHostInfo> #include <QHostInfo>
#include <QUuid> #include <QUuid>
namespace Tomahawk
{
namespace Accounts
{
namespace Hatchet
{
HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account ) HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
: SipPlugin( account ) : SipPlugin( account )
, m_sipState( Closed ) , m_sipState( Closed )
@@ -46,7 +54,9 @@ HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
{ {
tLog() << Q_FUNC_INFO; 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() )); connect( Servent::instance(), SIGNAL( dbSyncTriggered() ), this, SLOT( dbSyncTriggered() ));
/* /*
@@ -95,10 +105,10 @@ HatchetSipPlugin::isValid() const
} }
Tomahawk::Accounts::HatchetAccount* HatchetAccount*
HatchetSipPlugin::hatchetAccount() const HatchetSipPlugin::hatchetAccount() const
{ {
return qobject_cast< Tomahawk::Accounts::HatchetAccount* >( m_account ); return qobject_cast< HatchetAccount* >( m_account );
} }
@@ -133,7 +143,7 @@ HatchetSipPlugin::disconnectPlugin()
void void
HatchetSipPlugin::connectWebSocket() HatchetSipPlugin::connectWebSocket( const HatchetHelpers::AccessTokenInformation& accessTokenInformation )
{ {
tLog() << Q_FUNC_INFO; tLog() << Q_FUNC_INFO;
if ( m_webSocketThreadController ) if ( m_webSocketThreadController )
@@ -157,8 +167,7 @@ HatchetSipPlugin::connectWebSocket()
return; return;
} }
m_token = m_account->credentials()[ "dreamcatcher_access_token" ].toString(); m_token = accessTokenInformation.token;
if ( m_token.isEmpty() ) if ( m_token.isEmpty() )
{ {
@@ -585,3 +594,6 @@ HatchetSipPlugin::oplogFetched( const QString& sinceguid, const QString& /* last
} }
}
}
}

View File

@@ -32,6 +32,13 @@ class WebSocketThreadController;
const int VERSION = 1; const int VERSION = 1;
namespace Tomahawk
{
namespace Accounts
{
namespace Hatchet
{
class ACCOUNTDLLEXPORT HatchetSipPlugin : public SipPlugin class ACCOUNTDLLEXPORT HatchetSipPlugin : public SipPlugin
{ {
Q_OBJECT Q_OBJECT
@@ -63,14 +70,14 @@ public slots:
void webSocketDisconnected(); void webSocketDisconnected();
signals: signals:
void connectWebSocket() const; void connectWebSocket( const HatchetHelpers::AccessTokenInformation& ) const;
void disconnectWebSocket() const; void disconnectWebSocket() const;
void rawBytes( QByteArray bytes ) const; void rawBytes( QByteArray bytes ) const;
private slots: private slots:
void dbSyncTriggered(); void dbSyncTriggered();
void messageReceived( const QByteArray& msg ); 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 ); void oplogFetched( const QString& sinceguid, const QString& lastguid, const QList< dbop_ptr > ops );
private: private:
@@ -79,7 +86,7 @@ private:
void newPeer( const QVariantMap& valMap ); void newPeer( const QVariantMap& valMap );
void peerAuthorization( const QVariantMap& valMap ); void peerAuthorization( const QVariantMap& valMap );
void sendOplog( const QVariantMap& valMap ) const; void sendOplog( const QVariantMap& valMap ) const;
Tomahawk::Accounts::HatchetAccount* hatchetAccount() const; HatchetAccount* hatchetAccount() const;
QPointer< WebSocketThreadController > m_webSocketThreadController; QPointer< WebSocketThreadController > m_webSocketThreadController;
QString m_token; QString m_token;
@@ -91,4 +98,8 @@ private:
QHash< QString, QList< SipInfo > > m_sipInfoHash; QHash< QString, QList< SipInfo > > m_sipInfoHash;
}; };
}
}
}
#endif #endif

View File

@@ -68,7 +68,6 @@ WebSocketThreadController::run()
if ( m_webSocket && m_sip ) if ( m_webSocket && m_sip )
{ {
tLog() << Q_FUNC_INFO << "Have a valid websocket and parent"; 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( disconnectWebSocket() ), m_webSocket, SLOT( disconnectWs() ), Qt::QueuedConnection );
connect( m_sip, SIGNAL( rawBytes( QByteArray ) ), m_webSocket, SLOT( encodeMessage( QByteArray ) ), 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 ); connect( m_webSocket, SIGNAL( connected() ), m_sip, SLOT( webSocketConnected() ), Qt::QueuedConnection );