diff --git a/src/internet/googledriveclient.cpp b/src/internet/googledriveclient.cpp index f721edb70..fad73c2de 100644 --- a/src/internet/googledriveclient.cpp +++ b/src/internet/googledriveclient.cpp @@ -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(); } diff --git a/src/internet/googledriveclient.h b/src/internet/googledriveclient.h index 2da16f510..cecb2a1e9 100644 --- a/src/internet/googledriveclient.h +++ b/src/internet/googledriveclient.h @@ -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); diff --git a/src/internet/oauthenticator.cpp b/src/internet/oauthenticator.cpp index 2f981898d..dfdfa330c 100644 --- a/src/internet/oauthenticator.cpp +++ b/src/internet/oauthenticator.cpp @@ -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 Param; QList 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 Param; QList 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; diff --git a/src/internet/oauthenticator.h b/src/internet/oauthenticator.h index 1675056ca..05a0d5081 100644 --- a/src/internet/oauthenticator.h +++ b/src/internet/oauthenticator.h @@ -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