AddCloudWizard Consent Page + GoogleDrive refresh bug

.. the KentUniversity service has a consent page which is
   now added to the add cloud wizard as an option.

.. in testing this also found that the refresh of the google
   drive access token in MaybeRefreshCredentials() updated
   the value in app settings but not in the cloud service
   configuration settings. This is also fixed now for both
   the google drive and kent uni cloud services.
This commit is contained in:
Mark Liversedge
2017-09-23 15:59:07 +01:00
parent 243361e7d1
commit dc21935508
6 changed files with 100 additions and 4 deletions

View File

@@ -33,6 +33,7 @@
//
// 01. Select Service Class (e.g. Activities, Measures)
// 10. Select Cloud Service Type (via CloudServiceFactory)
// 15. Agree to terms of service (optional)
// 20. Authenticate Account (URL+Key, OAUTH or User/Pass)
// 25. Select Athlete [optional]
// 30. Settings (Folder,sync on startup, sync on import)
@@ -57,8 +58,9 @@ AddCloudWizard::AddCloudWizard(Context *context, QString sname) : QWizard(contex
if (service == "") {
setWindowTitle(tr("Add Cloud Wizard"));
setPage(01, new AddClass(this)); // done
setPage(10, new AddService(this)); // done
setPage(01, new AddClass(this));
setPage(10, new AddService(this));
setPage(15, new AddConsent(this));
cloudService = NULL; // not cloned yet
} else {
@@ -183,6 +185,16 @@ AddService::initializePage()
buttonlayout->addStretch();
}
int AddService::nextId() const
{
if (wizard->cloudService) {
if (wizard->cloudService->settings.value(CloudService::CloudServiceSetting::Consent, "") != "") return 15;
else return 20;
}
// loop round
return 10;
}
void
AddService::clicked(QString p)
{
@@ -197,6 +209,45 @@ AddService::clicked(QString p)
wizard->next();
}
// Consent to terms of service if needed
AddConsent::AddConsent(AddCloudWizard *parent) : QWizardPage(parent), wizard(parent), consented(false)
{
setTitle(tr("Terms of Service"));
setSubTitle(tr("Your consent is needed"));
layout = new QVBoxLayout;
setLayout(layout);
document = new QTextEdit(this);
document->setReadOnly(true);
layout->addWidget(document);
QHBoxLayout *buttons = new QHBoxLayout;
approve = new QPushButton(tr("Accept"), this);
buttons->addStretch();
buttons->addWidget(approve);
buttons->addStretch();
layout->addLayout(buttons);
connect(approve, SIGNAL(clicked(bool)), this, SLOT(setConsent()));
}
void AddConsent::setConsent()
{
consented = true;
emit completeChanged();
// move on if accepted
wizard->next();
}
void AddConsent::initializePage()
{
QStringList parts = wizard->cloudService->settings.value(CloudService::CloudServiceSetting::Consent, "::").split("::");
if (parts.count() < 2) document->setHtml("");
else document->setHtml(parts.at(1));
}
//Select Cloud type
AddAuth::AddAuth(AddCloudWizard *parent) : QWizardPage(parent), wizard(parent)
{
@@ -599,6 +650,7 @@ AddFinish::initializePage()
case CloudService::Local4:
case CloudService::Local5:
case CloudService::Local6: label=want.value().split(QRegExp("[<>/]")).last(); break;
case CloudService::Consent:
case CloudService::DefaultURL: break;
}
// no clue

View File

@@ -91,7 +91,7 @@ class AddService : public QWizardPage
void initializePage();
bool validate() const { return false; }
bool isComplete() const { return false; }
int nextId() const { return 20; }
int nextId() const;
public slots:
void clicked(QString);
@@ -104,6 +104,28 @@ class AddService : public QWizardPage
QScrollArea *scrollarea;
};
class AddConsent : public QWizardPage
{
Q_OBJECT
public:
AddConsent(AddCloudWizard *);
void initializePage();
bool isComplete() const { return consented; }
//bool isCommitPage() { return true; }
int nextId() const { return 20; }
public slots:
void setConsent();
private:
AddCloudWizard *wizard;
QVBoxLayout *layout;
QTextEdit *document;
QPushButton *approve;
bool consented;
};
class AddAuth : public QWizardPage
{
Q_OBJECT

View File

@@ -148,7 +148,7 @@ class CloudService : public QObject {
// entry points -- to list and accept the choice of athlete by the user
enum CloudServiceSetting { Username, Password, OAuthToken, Key, URL, DefaultURL, Folder, AthleteID,
Local1, Local2, Local3, Local4, Local5, Local6,
Combo1, Metadata1 } setting_;
Combo1, Metadata1, Consent } setting_;
QHash<CloudServiceSetting, QString> settings;
// When a service is instantiated by the cloud service factory, the configuration

View File

@@ -697,6 +697,8 @@ void GoogleDrive::MaybeRefreshCredentials() {
QString access_token = document.object()["access_token"].toString();
// LOCALLY MAINTAINED -- WILL BE AN ISSUE IF ALLOW >1 ACCOUNT XXX
setSetting(GC_GOOGLE_DRIVE_ACCESS_TOKEN, access_token);
setSetting(GC_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH, now.toString());
appsettings->setCValue(context_->athlete->cyclist, GC_GOOGLE_DRIVE_ACCESS_TOKEN, access_token);
appsettings->setCValue(context_->athlete->cyclist, GC_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH, now.toString());
} else {

View File

@@ -98,8 +98,24 @@ KentUniversity::KentUniversity(Context *context)
filetype = uploadType::CSV;
useMetric = true; // distance and duration metadata
QString consenttext= QString("<h2>Data Sharing Consent</h2>"
"<p>Your data will be shared with the researchers at the University of Kent as part of your participation in their study.</p>"
"<p>This data will include all telemetry data for each ride you share via a Google Drive folder. This data will be shared exactly as it can be viewed within GoldenCheetah.</p>"
"<p>This includes GPS, Power, Heart rate data and so on. No data is stripped and no data is resampled or adjusted.</p>"
"<h2>Controlling the data you share</h2>"
"<p>Only data that you explicitly upload via the Share menu will be shared. No data will be sent "
"without you explicitly triggering it. At any point you can revoke access to the data you have previously shared ("
"see revoking access below)."
"<h2>How Kent University will use your data</h2>"
"<p>The researchers at the University of Kent will use your data to support analyses as outlined in the study design.</p>"
"<p>This data may be shared with other researchers but will not include any personally identifiable information.</p>"
"<h2>Rekoving access to your data</h2>"
"<p>At any point you can revoke access to the data by unsharing the Google Drive folder using standard Google Drive functionality.</p>"
"<p>&nbsp;</p>");
// config
settings.clear();
settings.insert(Consent, QString("%1::%2").arg(GC_UOK_CONSENT).arg(consenttext));
settings.insert(Combo1, QString("%1::Scope::drive::drive.appdata::drive.file").arg(GC_UOK_GOOGLE_DRIVE_AUTH_SCOPE));
settings.insert(OAuthToken, GC_UOK_GOOGLE_DRIVE_ACCESS_TOKEN);
settings.insert(Folder, GC_UOK_GOOGLE_DRIVE_FOLDER);
@@ -714,6 +730,9 @@ void KentUniversity::MaybeRefreshCredentials() {
QString access_token = document.object()["access_token"].toString();
// LOCALLY MAINTAINED -- WILL BE AN ISSUE IF ALLOW >1 ACCOUNT XXX
setSetting(GC_UOK_GOOGLE_DRIVE_ACCESS_TOKEN, access_token);
setSetting(GC_UOK_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH, now.toString());
appsettings->setCValue(context_->athlete->cyclist, GC_UOK_GOOGLE_DRIVE_ACCESS_TOKEN, access_token);
appsettings->setCValue(context_->athlete->cyclist, GC_UOK_GOOGLE_DRIVE_LAST_ACCESS_TOKEN_REFRESH, now.toString());
} else {

View File

@@ -303,6 +303,7 @@
#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"