Factor out Google Drive specific code from OAuthenticator.

This commit is contained in:
John Maguire 2012-12-12 17:41:52 +01:00
parent 14c07cbaed
commit 8eea98ba66
4 changed files with 92 additions and 71 deletions

View File

@ -29,8 +29,23 @@ using namespace google_drive;
const char* File::kFolderMimeType = "application/vnd.google-apps.folder";
namespace {
static const char* kGoogleDriveFile = "https://www.googleapis.com/drive/v2/files/%1";
static const char* kGoogleDriveChanges = "https://www.googleapis.com/drive/v2/changes";
static const char* kGoogleDriveFile =
"https://www.googleapis.com/drive/v2/files/%1";
static const char* kGoogleDriveChanges =
"https://www.googleapis.com/drive/v2/changes";
static const char* kGoogleOAuthUserInfoEndpoint =
"https://www.googleapis.com/oauth2/v1/userinfo";
static const char* kOAuthEndpoint = "https://accounts.google.com/o/oauth2/auth";
static const char* kOAuthTokenEndpoint =
"https://accounts.google.com/o/oauth2/token";
static const char* kOAuthScope =
"https://www.googleapis.com/auth/drive.readonly "
"https://www.googleapis.com/auth/userinfo.email";
static const char* kClientId =
"679260893280.apps.googleusercontent.com";
static const char* kClientSecret =
"l3cWb8efUZsrBI4wmY3uKl6i";
}
QStringList File::parent_ids() const {
@ -74,12 +89,15 @@ Client::Client(QObject* parent)
ConnectResponse* Client::Connect(const QString& refresh_token) {
ConnectResponse* ret = new ConnectResponse(this);
OAuthenticator* oauth = new OAuthenticator(this);
OAuthenticator* oauth = new OAuthenticator(kClientId, kClientSecret, this);
if (refresh_token.isEmpty()) {
oauth->StartAuthorisation();
oauth->StartAuthorisation(
kOAuthEndpoint,
kOAuthTokenEndpoint,
kOAuthScope);
} else {
oauth->RefreshAuthorisation(refresh_token);
oauth->RefreshAuthorisation(kOAuthTokenEndpoint, refresh_token);
}
NewClosure(oauth, SIGNAL(Finished()),
@ -93,9 +111,36 @@ void Client::ConnectFinished(ConnectResponse* response, OAuthenticator* oauth) {
access_token_ = oauth->access_token();
expiry_time_ = oauth->expiry_time();
response->refresh_token_ = oauth->refresh_token();
response->user_email_ = oauth->user_email();
emit response->Finished();
// Fetch user email.
QUrl url(kGoogleOAuthUserInfoEndpoint);
QNetworkRequest request(url);
AddAuthorizationHeader(&request);
QNetworkReply* reply = network_->get(request);
NewClosure(reply, SIGNAL(finished()),
this, SLOT(FetchUserInfoFinished(ConnectResponse*, QNetworkReply*)),
response, reply);
}
void Client::FetchUserInfoFinished(
ConnectResponse* response, QNetworkReply* reply) {
reply->deleteLater();
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 200) {
qLog(Warning) << "Failed to get user info" << reply->readAll();
} else {
QJson::Parser parser;
bool ok = false;
QVariantMap result = parser.parse(reply, &ok).toMap();
if (!ok) {
qLog(Error) << "Failed to parse user info reply";
return;
}
qLog(Debug) << result;
response->user_email_ = result["email"].toString();
qLog(Debug) << response->user_email_;
}
emit response->Finished();
emit Authenticated();
}

View File

@ -155,6 +155,7 @@ signals:
private slots:
void ConnectFinished(ConnectResponse* response, OAuthenticator* oauth);
void FetchUserInfoFinished(ConnectResponse* response, QNetworkReply* reply);
void GetFileFinished(GetFileResponse* response, QNetworkReply* reply);
void ListChangesFinished(ListChangesResponse* response, QNetworkReply* reply);

View File

@ -10,38 +10,31 @@
#include "core/logging.h"
#include "internet/localredirectserver.h"
namespace {
const char* kGoogleOAuthEndpoint = "https://accounts.google.com/o/oauth2/auth";
const char* kGoogleOAuthTokenEndpoint =
"https://accounts.google.com/o/oauth2/token";
const char* kGoogleOAuthScope =
"https://www.googleapis.com/auth/drive.readonly "
"https://www.googleapis.com/auth/userinfo.email";
const char* kGoogleOAuthUserInfoEndpoint =
"https://www.googleapis.com/oauth2/v1/userinfo";
const char* kClientId = "679260893280.apps.googleusercontent.com";
const char* kClientSecret = "l3cWb8efUZsrBI4wmY3uKl6i";
} // namespace
OAuthenticator::OAuthenticator(QObject* parent)
: QObject(parent) {
OAuthenticator::OAuthenticator(
const QString& client_id,
const QString& client_secret,
QObject* parent)
: QObject(parent),
client_id_(client_id),
client_secret_(client_secret) {
}
void OAuthenticator::StartAuthorisation() {
void OAuthenticator::StartAuthorisation(
const QString& oauth_endpoint,
const QString& token_endpoint,
const QString& scope) {
token_endpoint_ = QUrl(token_endpoint);
LocalRedirectServer* server = new LocalRedirectServer(this);
server->Listen();
NewClosure(server, SIGNAL(Finished()),
this, SLOT(RedirectArrived(LocalRedirectServer*)), server);
QUrl url = QUrl(kGoogleOAuthEndpoint);
QUrl url = QUrl(oauth_endpoint);
url.addQueryItem("response_type", "code");
url.addQueryItem("client_id", kClientId);
url.addQueryItem("client_id", client_id_);
url.addQueryItem("redirect_uri", server->url().toString());
url.addQueryItem("scope", kGoogleOAuthScope);
url.addQueryItem("scope", scope);
QDesktopServices::openUrl(url);
}
@ -68,8 +61,8 @@ void OAuthenticator::RequestAccessToken(const QByteArray& code, const QUrl& url)
typedef QPair<QString, QString> Param;
QList<Param> parameters;
parameters << Param("code", code)
<< Param("client_id", kClientId)
<< Param("client_secret", kClientSecret)
<< Param("client_id", client_id_)
<< Param("client_secret", client_secret_)
<< Param("grant_type", "authorization_code")
// Even though we don't use this URI anymore, it must match the
// original one.
@ -82,7 +75,7 @@ void OAuthenticator::RequestAccessToken(const QByteArray& code, const QUrl& url)
QString post_data = params.join("&");
qLog(Debug) << post_data;
QNetworkRequest request = QNetworkRequest(QUrl(kGoogleOAuthTokenEndpoint));
QNetworkRequest request = QNetworkRequest(QUrl(token_endpoint_));
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
@ -114,49 +107,20 @@ void OAuthenticator::FetchAccessTokenFinished(QNetworkReply* reply) {
refresh_token_ = result["refresh_token"].toString();
SetExpiryTime(result["expires_in"].toInt());
// Fetch some basic user information
QUrl url = QUrl(kGoogleOAuthUserInfoEndpoint);
QNetworkRequest request(url);
request.setRawHeader(
"Authorization", QString("Bearer %1").arg(access_token_).toUtf8());
QNetworkReply* user_info_reply = network_.get(request);
NewClosure(user_info_reply, SIGNAL(finished()), this,
SLOT(FetchUserInfoFinished(QNetworkReply*)), user_info_reply);
}
void OAuthenticator::FetchUserInfoFinished(QNetworkReply* reply) {
reply->deleteLater();
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 200) {
qLog(Warning) << "Failed to get user info" << reply->readAll();
} else {
QJson::Parser parser;
bool ok = false;
QVariantMap result = parser.parse(reply, &ok).toMap();
if (!ok) {
qLog(Error) << "Failed to parse user info reply";
return;
}
qLog(Debug) << result;
user_email_ = result["email"].toString();
qLog(Debug) << user_email_;
}
emit Finished();
}
void OAuthenticator::RefreshAuthorisation(const QString& refresh_token) {
void OAuthenticator::RefreshAuthorisation(
const QString& token_endpoint,
const QString& refresh_token) {
refresh_token_ = refresh_token;
QUrl url = QUrl(kGoogleOAuthTokenEndpoint);
QUrl url(token_endpoint);
typedef QPair<QString, QString> Param;
QList<Param> parameters;
parameters << Param("client_id", kClientId)
<< Param("client_secret", kClientSecret)
parameters << Param("client_id", client_id_)
<< Param("client_secret", client_secret_)
<< Param("grant_type", "refresh_token")
<< Param("refresh_token", refresh_token);
QStringList params;

View File

@ -12,9 +12,17 @@ class QTcpSocket;
class OAuthenticator : public QObject {
Q_OBJECT
public:
explicit OAuthenticator(QObject* parent = 0);
void StartAuthorisation();
void RefreshAuthorisation(const QString& refresh_token);
OAuthenticator(
const QString& client_id,
const QString& client_secret,
QObject* parent = 0);
void StartAuthorisation(
const QString& oauth_endpoint,
const QString& token_endpoint,
const QString& scope);
void RefreshAuthorisation(
const QString& token_endpoint,
const QString& refresh_token);
// Token to use now.
const QString& access_token() const { return access_token_; }
@ -32,7 +40,6 @@ class OAuthenticator : public QObject {
void RedirectArrived(LocalRedirectServer* server);
void FetchAccessTokenFinished(QNetworkReply* reply);
void RefreshAccessTokenFinished(QNetworkReply* reply);
void FetchUserInfoFinished(QNetworkReply* reply);
private:
QByteArray ParseHttpRequest(const QByteArray& request) const;
@ -45,6 +52,10 @@ class OAuthenticator : public QObject {
QString refresh_token_;
QDateTime expiry_time_;
QString user_email_;
const QString client_id_;
const QString client_secret_;
QUrl token_endpoint_;
};
#endif