Factor out Google Drive specific code from OAuthenticator.
This commit is contained in:
parent
14c07cbaed
commit
8eea98ba66
|
@ -29,8 +29,23 @@ using namespace google_drive;
|
||||||
const char* File::kFolderMimeType = "application/vnd.google-apps.folder";
|
const char* File::kFolderMimeType = "application/vnd.google-apps.folder";
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static const char* kGoogleDriveFile = "https://www.googleapis.com/drive/v2/files/%1";
|
static const char* kGoogleDriveFile =
|
||||||
static const char* kGoogleDriveChanges = "https://www.googleapis.com/drive/v2/changes";
|
"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 {
|
QStringList File::parent_ids() const {
|
||||||
|
@ -74,12 +89,15 @@ Client::Client(QObject* parent)
|
||||||
|
|
||||||
ConnectResponse* Client::Connect(const QString& refresh_token) {
|
ConnectResponse* Client::Connect(const QString& refresh_token) {
|
||||||
ConnectResponse* ret = new ConnectResponse(this);
|
ConnectResponse* ret = new ConnectResponse(this);
|
||||||
OAuthenticator* oauth = new OAuthenticator(this);
|
OAuthenticator* oauth = new OAuthenticator(kClientId, kClientSecret, this);
|
||||||
|
|
||||||
if (refresh_token.isEmpty()) {
|
if (refresh_token.isEmpty()) {
|
||||||
oauth->StartAuthorisation();
|
oauth->StartAuthorisation(
|
||||||
|
kOAuthEndpoint,
|
||||||
|
kOAuthTokenEndpoint,
|
||||||
|
kOAuthScope);
|
||||||
} else {
|
} else {
|
||||||
oauth->RefreshAuthorisation(refresh_token);
|
oauth->RefreshAuthorisation(kOAuthTokenEndpoint, refresh_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewClosure(oauth, SIGNAL(Finished()),
|
NewClosure(oauth, SIGNAL(Finished()),
|
||||||
|
@ -93,9 +111,36 @@ void Client::ConnectFinished(ConnectResponse* response, OAuthenticator* oauth) {
|
||||||
access_token_ = oauth->access_token();
|
access_token_ = oauth->access_token();
|
||||||
expiry_time_ = oauth->expiry_time();
|
expiry_time_ = oauth->expiry_time();
|
||||||
response->refresh_token_ = oauth->refresh_token();
|
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();
|
emit Authenticated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,7 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ConnectFinished(ConnectResponse* response, OAuthenticator* oauth);
|
void ConnectFinished(ConnectResponse* response, OAuthenticator* oauth);
|
||||||
|
void FetchUserInfoFinished(ConnectResponse* response, QNetworkReply* reply);
|
||||||
void GetFileFinished(GetFileResponse* response, QNetworkReply* reply);
|
void GetFileFinished(GetFileResponse* response, QNetworkReply* reply);
|
||||||
void ListChangesFinished(ListChangesResponse* response, QNetworkReply* reply);
|
void ListChangesFinished(ListChangesResponse* response, QNetworkReply* reply);
|
||||||
|
|
||||||
|
|
|
@ -10,38 +10,31 @@
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "internet/localredirectserver.h"
|
#include "internet/localredirectserver.h"
|
||||||
|
|
||||||
namespace {
|
OAuthenticator::OAuthenticator(
|
||||||
|
const QString& client_id,
|
||||||
const char* kGoogleOAuthEndpoint = "https://accounts.google.com/o/oauth2/auth";
|
const QString& client_secret,
|
||||||
const char* kGoogleOAuthTokenEndpoint =
|
QObject* parent)
|
||||||
"https://accounts.google.com/o/oauth2/token";
|
: QObject(parent),
|
||||||
const char* kGoogleOAuthScope =
|
client_id_(client_id),
|
||||||
"https://www.googleapis.com/auth/drive.readonly "
|
client_secret_(client_secret) {
|
||||||
"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) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
LocalRedirectServer* server = new LocalRedirectServer(this);
|
||||||
server->Listen();
|
server->Listen();
|
||||||
|
|
||||||
NewClosure(server, SIGNAL(Finished()),
|
NewClosure(server, SIGNAL(Finished()),
|
||||||
this, SLOT(RedirectArrived(LocalRedirectServer*)), server);
|
this, SLOT(RedirectArrived(LocalRedirectServer*)), server);
|
||||||
|
|
||||||
QUrl url = QUrl(kGoogleOAuthEndpoint);
|
QUrl url = QUrl(oauth_endpoint);
|
||||||
url.addQueryItem("response_type", "code");
|
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("redirect_uri", server->url().toString());
|
||||||
url.addQueryItem("scope", kGoogleOAuthScope);
|
url.addQueryItem("scope", scope);
|
||||||
|
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl(url);
|
||||||
}
|
}
|
||||||
|
@ -68,8 +61,8 @@ void OAuthenticator::RequestAccessToken(const QByteArray& code, const QUrl& url)
|
||||||
typedef QPair<QString, QString> Param;
|
typedef QPair<QString, QString> Param;
|
||||||
QList<Param> parameters;
|
QList<Param> parameters;
|
||||||
parameters << Param("code", code)
|
parameters << Param("code", code)
|
||||||
<< Param("client_id", kClientId)
|
<< Param("client_id", client_id_)
|
||||||
<< Param("client_secret", kClientSecret)
|
<< Param("client_secret", client_secret_)
|
||||||
<< Param("grant_type", "authorization_code")
|
<< Param("grant_type", "authorization_code")
|
||||||
// Even though we don't use this URI anymore, it must match the
|
// Even though we don't use this URI anymore, it must match the
|
||||||
// original one.
|
// original one.
|
||||||
|
@ -82,7 +75,7 @@ void OAuthenticator::RequestAccessToken(const QByteArray& code, const QUrl& url)
|
||||||
QString post_data = params.join("&");
|
QString post_data = params.join("&");
|
||||||
qLog(Debug) << post_data;
|
qLog(Debug) << post_data;
|
||||||
|
|
||||||
QNetworkRequest request = QNetworkRequest(QUrl(kGoogleOAuthTokenEndpoint));
|
QNetworkRequest request = QNetworkRequest(QUrl(token_endpoint_));
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader,
|
request.setHeader(QNetworkRequest::ContentTypeHeader,
|
||||||
"application/x-www-form-urlencoded");
|
"application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
@ -114,49 +107,20 @@ void OAuthenticator::FetchAccessTokenFinished(QNetworkReply* reply) {
|
||||||
refresh_token_ = result["refresh_token"].toString();
|
refresh_token_ = result["refresh_token"].toString();
|
||||||
SetExpiryTime(result["expires_in"].toInt());
|
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();
|
emit Finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OAuthenticator::RefreshAuthorisation(const QString& refresh_token) {
|
void OAuthenticator::RefreshAuthorisation(
|
||||||
|
const QString& token_endpoint,
|
||||||
|
const QString& refresh_token) {
|
||||||
refresh_token_ = refresh_token;
|
refresh_token_ = refresh_token;
|
||||||
|
|
||||||
QUrl url = QUrl(kGoogleOAuthTokenEndpoint);
|
QUrl url(token_endpoint);
|
||||||
|
|
||||||
typedef QPair<QString, QString> Param;
|
typedef QPair<QString, QString> Param;
|
||||||
QList<Param> parameters;
|
QList<Param> parameters;
|
||||||
parameters << Param("client_id", kClientId)
|
parameters << Param("client_id", client_id_)
|
||||||
<< Param("client_secret", kClientSecret)
|
<< Param("client_secret", client_secret_)
|
||||||
<< Param("grant_type", "refresh_token")
|
<< Param("grant_type", "refresh_token")
|
||||||
<< Param("refresh_token", refresh_token);
|
<< Param("refresh_token", refresh_token);
|
||||||
QStringList params;
|
QStringList params;
|
||||||
|
|
|
@ -12,9 +12,17 @@ class QTcpSocket;
|
||||||
class OAuthenticator : public QObject {
|
class OAuthenticator : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit OAuthenticator(QObject* parent = 0);
|
OAuthenticator(
|
||||||
void StartAuthorisation();
|
const QString& client_id,
|
||||||
void RefreshAuthorisation(const QString& refresh_token);
|
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.
|
// Token to use now.
|
||||||
const QString& access_token() const { return access_token_; }
|
const QString& access_token() const { return access_token_; }
|
||||||
|
@ -32,7 +40,6 @@ class OAuthenticator : public QObject {
|
||||||
void RedirectArrived(LocalRedirectServer* server);
|
void RedirectArrived(LocalRedirectServer* server);
|
||||||
void FetchAccessTokenFinished(QNetworkReply* reply);
|
void FetchAccessTokenFinished(QNetworkReply* reply);
|
||||||
void RefreshAccessTokenFinished(QNetworkReply* reply);
|
void RefreshAccessTokenFinished(QNetworkReply* reply);
|
||||||
void FetchUserInfoFinished(QNetworkReply* reply);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray ParseHttpRequest(const QByteArray& request) const;
|
QByteArray ParseHttpRequest(const QByteArray& request) const;
|
||||||
|
@ -45,6 +52,10 @@ class OAuthenticator : public QObject {
|
||||||
QString refresh_token_;
|
QString refresh_token_;
|
||||||
QDateTime expiry_time_;
|
QDateTime expiry_time_;
|
||||||
QString user_email_;
|
QString user_email_;
|
||||||
|
|
||||||
|
const QString client_id_;
|
||||||
|
const QString client_secret_;
|
||||||
|
QUrl token_endpoint_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue