138 changes: 4 additions & 134 deletions src/Cloud/OAuthDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "Colors.h"
#include "TimeUtils.h"

#include "GoogleDrive.h"
#include "PolarFlow.h"

#include <QJsonParseError>
Expand All @@ -44,10 +43,7 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service
if (service->id() == "Strava") site = this->site = STRAVA;
if (service->id() == "Dropbox") site = this->site = DROPBOX;
if (service->id() == "Cycling Analytics") site = this->site = CYCLING_ANALYTICS;
if (service->id() == "Google Calendar") site = this->site = GOOGLE_CALENDAR;
if (service->id() == "Google Drive") site = this->site = GOOGLE_DRIVE;
if (service->id() == "Nolio") site = this->site = NOLIO;
if (service->id() == "University of Kent") site = this->site = KENTUNI;
if (service->id() == "Today's Plan") site = this->site = TODAYSPLAN;
if (service->id() == "Withings") site = this->site = WITHINGS;
if (service->id() == "PolarFlow") site = this->site = POLAR;
Expand Down Expand Up @@ -129,37 +125,6 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service
urlstr.append("response_type=code&");
urlstr.append("approval_prompt=force");

} else if (site == GOOGLE_CALENDAR) {
// OAUTH 2.0 - Google flow for installed applications
urlstr = QString("https://accounts.google.com/o/oauth2/auth?");
urlstr.append("scope=https://www.googleapis.com/auth/calendar&");
urlstr.append("redirect_uri=urn:ietf:wg:oauth:2.0:oob&");
urlstr.append("response_type=code&");
urlstr.append("client_id=").append(GC_GOOGLE_CALENDAR_CLIENT_ID);

} else if (site == GOOGLE_DRIVE) {

const QString scope = service->getSetting(GC_GOOGLE_DRIVE_AUTH_SCOPE, "drive.appdata").toString();
// OAUTH 2.0 - Google flow for installed applications
urlstr = QString("https://accounts.google.com/o/oauth2/auth?");
// We only request access to the application data folder, not all files.
urlstr.append("scope=https://www.googleapis.com/auth/" + scope + "&");
urlstr.append("redirect_uri=urn:ietf:wg:oauth:2.0:oob&");
urlstr.append("response_type=code&");
urlstr.append("client_id=").append(GC_GOOGLE_DRIVE_CLIENT_ID);

} else if (site == KENTUNI) {

const QString scope = service->getSetting(GC_UOK_GOOGLE_DRIVE_AUTH_SCOPE, "drive.appdata").toString();

// OAUTH 2.0 - Google flow for installed applications
urlstr = QString("https://accounts.google.com/o/oauth2/auth?");
// We only request access to the application data folder, not all files.
urlstr.append("scope=https://www.googleapis.com/auth/" + scope + "&");
urlstr.append("redirect_uri=urn:ietf:wg:oauth:2.0:oob&");
urlstr.append("response_type=code&");
urlstr.append("client_id=").append(GC_GOOGLE_DRIVE_CLIENT_ID);

} else if (site == TODAYSPLAN) {

//urlstr = QString("https://whats.todaysplan.com.au/en/authorize/"); //XXX fixup below when pages.cpp goes
Expand All @@ -169,7 +134,7 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service

} else if (site == POLAR) {

// OAUTH 2.0 - Google flow for installed applications
// OAUTH 2.0 - Polar flow for installed applications
urlstr = QString("%1?").arg(GC_POLARFLOW_OAUTH_URL);
// We only request access to the application data folder, not all files.
urlstr.append("response_type=code&");
Expand Down Expand Up @@ -202,13 +167,12 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service
//
// STEP 1: LOGIN AND AUTHORISE THE APPLICATION
//
if (site == NOLIO || site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == POLAR || site == SPORTTRACKS || site == GOOGLE_CALENDAR || site == GOOGLE_DRIVE || site == KENTUNI || site == TODAYSPLAN || site == WITHINGS) {
if (site == NOLIO || site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == POLAR || site == SPORTTRACKS || site == TODAYSPLAN || site == WITHINGS) {
url = QUrl(urlstr);
view->setUrl(url);

// connects
connect(view, SIGNAL(urlChanged(const QUrl&)), this, SLOT(urlChanged(const QUrl&)));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
}
}

Expand Down Expand Up @@ -383,60 +347,6 @@ OAuthDialog::urlChanged(const QUrl &url)
}
}

//
// GOOGLE DRIVE gets the code in the HTML title field (different to other services)
//
void
OAuthDialog::loadFinished(bool ok)
{

if (site == GOOGLE_CALENDAR || site == GOOGLE_DRIVE || site == KENTUNI) {

if (ok && url.toString().startsWith("https://accounts.google.com/o/oauth2/auth")) {

// retrieve the code from the HTML page title
QString title = view->title();

if (title.contains("code")) {

QString code = title.right(title.length()-title.indexOf("code=")-5);
QByteArray data;
QUrlQuery params;
QString urlstr = "https://www.googleapis.com/oauth2/v3/token?";
if (site == GOOGLE_CALENDAR) {
params.addQueryItem("client_id", GC_GOOGLE_CALENDAR_CLIENT_ID);
} else if (site == GOOGLE_DRIVE || site == KENTUNI) {
params.addQueryItem("client_id", GC_GOOGLE_DRIVE_CLIENT_ID);
}

if (site == GOOGLE_CALENDAR) {
params.addQueryItem("client_secret", GC_GOOGLE_CALENDAR_CLIENT_SECRET);
} else if (site == GOOGLE_DRIVE || site == KENTUNI) {
params.addQueryItem("client_secret", GC_GOOGLE_DRIVE_CLIENT_SECRET);
}

params.addQueryItem("code", code);
params.addQueryItem("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");
params.addQueryItem("grant_type", "authorization_code");

data.append(params.query(QUrl::FullyEncoded));

// trade-in the temporary access code retrieved by the
// Call-Back URL for the finale token
QUrl url = QUrl(urlstr);
QNetworkRequest request = QNetworkRequest(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

// not get the final token - ignoring errors
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> & )), this, SLOT(onSslErrors(QNetworkReply*, const QList<QSslError> & )));
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkRequestFinished(QNetworkReply*)));
manager->post(request, data);
}
}
}
}

//
// STEP 3: REFRESH AND ACCESS TOKEN RECEIVED
//
Expand Down Expand Up @@ -474,20 +384,6 @@ OAuthDialog::networkRequestFinished(QNetworkReply *reply)
}
}

// if we failed to extract then we have a big problem
// google uses a refresh token so trap for them only
if (((site == GOOGLE_CALENDAR || site == GOOGLE_DRIVE || site == KENTUNI) && refresh_token == "") ||
access_token == "" ) {
// Something failed.
// Only Google uses both refresh and access tokens.
QString error = QString(tr("Error retrieving authoriation credentials"));
QMessageBox oautherr(QMessageBox::Critical, tr("Authorization Error"), error);
oautherr.setDetailedText(error);
oautherr.exec();

return;
}

// now set the tokens etc
if (site == DROPBOX) {

Expand Down Expand Up @@ -558,39 +454,13 @@ OAuthDialog::networkRequestFinished(QNetworkReply *reply)
QMessageBox information(QMessageBox::Information, tr("Information"), info);
information.exec();

} else if (site == GOOGLE_CALENDAR) {
// remove the Google Page first
url = QUrl("http://www.goldencheetah.org");
view->setUrl(url);
appsettings->setCValue(context->athlete->cyclist, GC_GOOGLE_CALENDAR_REFRESH_TOKEN, refresh_token);
QString info = QString(tr("Google Calendar authorization was successful."));
QMessageBox information(QMessageBox::Information,
tr("Information"), info);
information.exec();

} else if (site == KENTUNI) {

service->setSetting(GC_UOK_GOOGLE_DRIVE_REFRESH_TOKEN, refresh_token);
service->setSetting(GC_UOK_GOOGLE_DRIVE_ACCESS_TOKEN, access_token);
service->setSetting(GC_UOK_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH, QDateTime::currentDateTime());
QString info = QString(tr("Kent University Google Drive authorization was successful."));
QMessageBox information(QMessageBox::Information, tr("Information"), info);
information.exec();

} else if (site == GOOGLE_DRIVE) {

service->setSetting(GC_GOOGLE_DRIVE_REFRESH_TOKEN, refresh_token);
service->setSetting(GC_GOOGLE_DRIVE_ACCESS_TOKEN, access_token);
service->setSetting(GC_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH, QDateTime::currentDateTime());
QString info = QString(tr("Google Drive authorization was successful."));
QMessageBox information(QMessageBox::Information, tr("Information"), info);
information.exec();

} else if (site == TODAYSPLAN) {

service->setSetting(GC_TODAYSPLAN_TOKEN, access_token);
QString info = QString(tr("Today's Plan authorization was successful."));
QMessageBox information(QMessageBox::Information, tr("Information"), info);
information.exec();

} else if (site == XERT) {

service->setSetting(GC_XERT_TOKEN, access_token);
Expand Down
6 changes: 1 addition & 5 deletions src/Cloud/OAuthDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,11 @@ class OAuthDialog : public QDialog
STRAVA,
DROPBOX,
CYCLING_ANALYTICS,
GOOGLE_CALENDAR,
GOOGLE_DRIVE,
NOLIO,
SPORTTRACKS,
TODAYSPLAN,
WITHINGS,
POLAR,
KENTUNI,
XERT,
RIDEWITHGPS
} OAuthSite;
Expand All @@ -68,9 +65,8 @@ class OAuthDialog : public QDialog
bool sslLibMissing() { return noSSLlib; }

private slots:
// Strava/Cyclinganalytics/Google
// Strava/Cyclinganalytics
void urlChanged(const QUrl& url);
void loadFinished(bool ok);
void networkRequestFinished(QNetworkReply *reply);
void onSslErrors(QNetworkReply *reply, const QList<QSslError>&error);

Expand Down
16 changes: 0 additions & 16 deletions src/Core/Secrets.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,6 @@
#ifndef _GC_SECRETS_H
#define _GC_SECRETS_H 1

// used by OAuthDialog.cpp and CalDAV.cpp for Google Calendar
#ifndef GC_GOOGLE_CALENDAR_CLIENT_SECRET
#define GC_GOOGLE_CALENDAR_CLIENT_SECRET "__GC_GOOGLE_CALENDAR_CLIENT_SECRET__"
#endif

// used by OAuthDialog.cpp and GoogleDrive.cpp for Google Drive
#ifndef GC_GOOGLE_DRIVE_CLIENT_ID
#define GC_GOOGLE_DRIVE_CLIENT_ID "__GC_GOOGLE_DRIVE_CLIENT_ID__"
#endif
#ifndef GC_GOOGLE_DRIVE_CLIENT_SECRET
#define GC_GOOGLE_DRIVE_CLIENT_SECRET "__GC_GOOGLE_DRIVE_CLIENT_SECRET__"
#endif
#ifndef GC_GOOGLE_DRIVE_API_KEY
#define GC_GOOGLE_DRIVE_API_KEY "__GC_GOOGLE_DRIVE_API_KEY__"
#endif

#ifndef GC_CLOUD_OPENDATA_SECRET
#define OPENDATA_DISABLE
#define GC_CLOUD_OPENDATA_SECRET "__GC_CLOUD_OPENDATA_SECRET__"
Expand Down
2 changes: 0 additions & 2 deletions src/Core/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,8 +705,6 @@ GSettings::upgradeAthlete(QString athlete) {
migrateCValue(athlete, GC_DVUSER);
migrateCValue(athlete, GC_DVPASS);
migrateCValue(athlete, GC_DVCALDAVTYPE);
migrateCValue(athlete, GC_DVGOOGLE_CALID);
migrateCValue(athlete, GC_GOOGLE_CALENDAR_REFRESH_TOKEN);
migrateCValue(athlete, GC_STRAVA_TOKEN);
migrateCValue(athlete, GC_CYCLINGANALYTICS_TOKEN);

Expand Down
36 changes: 10 additions & 26 deletions src/Core/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@
#define GC_UNIT_METRIC "Metric"
#define GC_UNIT_IMPERIAL "Imperial"

//Google Calendar-CALDAV oauthkeys / see also Athlete parameter
#define GC_GOOGLE_CALENDAR_CLIENT_ID "426009671216-c588t1u6hafep30tfs7g0g1nuo72s8ko.apps.googleusercontent.com"

//Today's Plan
#define GC_TODAYSPLAN_CLIENT_ID "GoldenCheetah" // app id

Expand Down Expand Up @@ -366,46 +363,28 @@
#define GC_DVUSER "<athlete-private>dv/user"
#define GC_DVPASS "<athlete-private>dv/pass"
#define GC_DVCALDAVTYPE "<athlete-private>dv/type"
#define GC_DVGOOGLE_CALID "<athlete-private>dv/googlecalid"
#define GC_DVGOOGLE_DRIVE "<athlete-private>dv/googledrive"

//Dropbox oauth keys
#define GC_DROPBOX_TOKEN "<athlete-private>dropbox/token"
#define GC_DROPBOX_FOLDER "<athlete-private>dropbox/folder"

//Google oauth keys
#define GC_GOOGLE_DRIVE_AUTH_SCOPE "<athlete-private>google-drive/auth_scope"
#define GC_GOOGLE_DRIVE_ACCESS_TOKEN "<athlete-private>google-drive/access_token"
#define GC_GOOGLE_DRIVE_REFRESH_TOKEN "<athlete-private>google-drive/refresh_token"
#define GC_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH "<athlete-private>google-drive/last_access_token_refresh"

#define GC_GOOGLE_DRIVE_FOLDER "<athlete-private>google-drive/folder"
#define GC_GOOGLE_DRIVE_FOLDER_ID "<athlete-private>google-drive/folder_id"

//University of Kent (same as google drive)
#define GC_UOK_CONSENT "<athlete-private>uok-google-drive/consent"
#define GC_UOK_GOOGLE_DRIVE_AUTH_SCOPE "<athlete-private>uok-google-drive/auth_scope"
#define GC_UOK_GOOGLE_DRIVE_ACCESS_TOKEN "<athlete-private>uok-google-drive/access_token"
#define GC_UOK_GOOGLE_DRIVE_REFRESH_TOKEN "<athlete-private>uok-google-drive/refresh_token"
#define GC_UOK_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH "<athlete-private>uok-google-drive/last_access_token_refresh"

#define GC_UOK_GOOGLE_DRIVE_FOLDER "<athlete-private>uok-google-drive/folder"
#define GC_UOK_GOOGLE_DRIVE_FOLDER_ID "<athlete-private>uok-google-drive/folder_id"

//Withings
#define GC_WITHINGS_TOKEN "<athlete-private>withings_token"
#define GC_WITHINGS_SECRET "<athlete-private>withings_secret"

//Nokia
#define GC_NOKIA_TOKEN "<athlete-private>nokia_token"
#define GC_NOKIA_REFRESH_TOKEN "<athlete-private>nokia_refresh_token"
//Google Calendar-CALDAV oauthkeys
#define GC_GOOGLE_CALENDAR_REFRESH_TOKEN "<athlete-private>google_cal_refresh_token"

//Strava
#define GC_STRAVA_TOKEN "<athlete-private>strava_token"
#define GC_STRAVA_REFRESH_TOKEN "<athlete-private>strava_refresh_token"
#define GC_STRAVA_LAST_REFRESH "<athlete-private>strava_last_refresh"
#define GC_STRAVA_ACTIVITY_NAME "<athlete-private>strava_metaname"

//Cycling Analytics
#define GC_CYCLINGANALYTICS_TOKEN "<athlete-private>cyclinganalytics_token"

//Today's Plan
#define GC_TODAYSPLAN_TOKEN "<athlete-private>todaysplan_token"
#define GC_TODAYSPLAN_URL "<athlete-private>todaysplan_url"
Expand All @@ -417,26 +396,31 @@
#define GC_SIXCYCLE_USER "<athlete-private>sixcycle_user"
#define GC_SIXCYCLE_PASS "<athlete-private>sixcycle_pass"
#define GC_SIXCYCLE_URL "<athlete-private>sixcycle_url"

// Polar Flow
#define GC_POLARFLOW_TOKEN "<athlete-private>polarflow_token"
#define GC_POLARFLOW_USER_ID "<athlete-private>polarflow_user_id"

// SportTracks
#define GC_SPORTTRACKS_TOKEN "<athlete-private>sporttracks/sporttracks_token"
#define GC_SPORTTRACKS_REFRESH_TOKEN "<athlete-private>sporttracks/refresh_token"
#define GC_SPORTTRACKS_LAST_REFRESH "<athlete-private>sporttracks/last_refresh"

// Xert
#define GC_XERTUSER "<athlete-private>xert/user"
#define GC_XERTPASS "<athlete-private>xert/pass"
#define GC_XERT_TOKEN "<athlete-private>xert/xert_token"
#define GC_XERT_REFRESH_TOKEN "<athlete-private>xert/refresh_token"
#define GC_XERT_LAST_REFRESH "<athlete-private>xert/last_refresh"

// Nolio
#define GC_NOLIO_ACCESS_TOKEN "<global-general>nolio_access_token"
#define GC_NOLIO_REFRESH_TOKEN "<global-general>nolio_refresh_token"
#define GC_NOLIO_LAST_REFRESH "<global-general>nolio_last_refresh"
#define GC_NOLIO_URL "<athlete-private>nolio_url"
#define GC_NOLIO_ATHLETE_ID "<athlete-private>nolio_athlete_id"
#define GC_NOLIO_ATHLETE_NAME "<athlete-private>nolio_athlete_name"

// --------------------------------------------------------------------------------
#include <QSettings>
#include <QFileInfo>
Expand Down
1 change: 0 additions & 1 deletion src/Gui/AthletePages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
#include "HelpWhatsThis.h"
#include "GcUpgrade.h"
#include "Dropbox.h"
#include "GoogleDrive.h"
#include "LocalFileStore.h"
#include "Secrets.h"
#include "Utils.h"
Expand Down
18 changes: 2 additions & 16 deletions src/Gui/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@
#include "ErgDBDownloadDialog.h"
#include "AddDeviceWizard.h"
#include "Dropbox.h"
#include "GoogleDrive.h"
#include "KentUniversity.h"
#include "SixCycle.h"
#include "OpenData.h"
#include "AddCloudWizard.h"
Expand Down Expand Up @@ -2481,14 +2479,8 @@ MainWindow::uploadCloud(QAction *action)
// & removed to avoid issues with kde AutoCheckAccelerators
QString actionText = QString(action->text()).replace("&", "");

if (actionText == "University of Kent") {
CloudService *db = CloudServiceFactory::instance().newService(action->data().toString(), currentAthleteTab->context);
KentUniversityUploadDialog uploader(this, db, currentAthleteTab->context->ride);
uploader.exec();
} else {
CloudService *db = CloudServiceFactory::instance().newService(action->data().toString(), currentAthleteTab->context);
CloudService::upload(this, currentAthleteTab->context, db, currentAthleteTab->context->ride);
}
CloudService *db = CloudServiceFactory::instance().newService(action->data().toString(), currentAthleteTab->context);
CloudService::upload(this, currentAthleteTab->context, db, currentAthleteTab->context->ride);
}
}

Expand Down Expand Up @@ -2768,9 +2760,6 @@ MainWindow::setUploadMenu()
QAction *service = new QAction(NULL);
service->setText(s->uiName());
service->setData(name);

// Kent doesn't use the standard uploader, we trap for that
// in the upload action method
uploadMenu->addAction(service);
}
}
Expand All @@ -2787,9 +2776,6 @@ MainWindow::setSyncMenu()

if (s->capabilities() & CloudService::Query) {

// We don't sync with Kent
if (s->id() == "University of Kent") continue;

// we need the technical name to identify the service to be called
QAction *service = new QAction(NULL);
service->setText(s->uiName());
Expand Down
1 change: 0 additions & 1 deletion src/Gui/Pages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include "HelpWhatsThis.h"
#include "GcUpgrade.h"
#include "Dropbox.h"
#include "GoogleDrive.h"
#include "LocalFileStore.h"
#include "Secrets.h"
#include "Utils.h"
Expand Down
1 change: 0 additions & 1 deletion src/Resources/application.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@
<file>images/services/strava_connect.png</file>
<file>images/services/cyclinganalytics.png</file>
<file>images/services/dropbox.png</file>
<file>images/services/googledrive.png</file>
<file>images/services/localstore.png</file>
<file>images/services/ridewithgps.png</file>
<file>images/services/selfloops.png</file>
Expand Down
2 changes: 0 additions & 2 deletions src/src.pro
Original file line number Diff line number Diff line change
Expand Up @@ -603,8 +603,6 @@ greaterThan(QT_MAJOR_VERSION, 4) {
# Features that only work with QT5 or higher
SOURCES += Cloud/Dropbox.cpp
HEADERS += Cloud/Dropbox.h
SOURCES += Cloud/GoogleDrive.cpp Cloud/KentUniversity.cpp
HEADERS += Cloud/GoogleDrive.h Cloud/KentUniversity.h
SOURCES += Cloud/OpenData.cpp
HEADERS += Cloud/OpenData.h

Expand Down