From c0f53c746f172b9ec329380b39112f09c58b5e5e Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Mon, 21 Oct 2024 18:25:36 +0200 Subject: [PATCH] detect the terms of service app is requiring the user to sign them will query the sign state for the terms of service and automatically pause or resume sync Signed-off-by: Matthieu Gallien --- src/gui/accountsettings.cpp | 3 +++ src/gui/accountstate.cpp | 11 +++++++++++ src/gui/accountstate.h | 6 +++++- src/gui/application.cpp | 2 ++ src/gui/connectionvalidator.cpp | 31 ++++++++++++++++++++++++++++++- src/gui/connectionvalidator.h | 5 ++++- src/gui/folder.cpp | 6 ++++++ src/gui/owncloudgui.cpp | 10 ++++++++++ src/gui/owncloudgui.h | 2 +- 9 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 210ed222ddbce..841cf3a272f1f 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -1290,6 +1290,9 @@ void AccountSettings::slotAccountStateChanged() // we can't end up here as the whole block is ifdeffed Q_UNREACHABLE(); break; + case AccountState::NeedToSignTermsOfService: + showConnectionLabel(tr("You need to accept the terms of service")); + break; } } else { // ownCloud is not yet configured. diff --git a/src/gui/accountstate.cpp b/src/gui/accountstate.cpp index 36cfce37ad561..c5393885d6dec 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -161,6 +161,8 @@ QString AccountState::stateString(State state) return tr("Configuration error"); case AskingCredentials: return tr("Asking Credentials"); + case NeedToSignTermsOfService: + return tr("Need the user to accept the terms of service"); } return tr("Unknown account state"); } @@ -348,6 +350,12 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta _lastConnectionValidatorStatus = status; + if ((_lastConnectionValidatorStatus == ConnectionValidator::NeedToSignTermsOfService && status == ConnectionValidator::Connected) || + status == ConnectionValidator::NeedToSignTermsOfService) { + + emit termsOfServiceChanged(_account); + } + // Come online gradually from 503, captive portal(redirection) or maintenance mode if (status == ConnectionValidator::Connected && (_connectionStatus == ConnectionValidator::ServiceUnavailable @@ -426,6 +434,9 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta setState(NetworkError); updateRetryCount(); break; + case ConnectionValidator::NeedToSignTermsOfService: + setState(NeedToSignTermsOfService); + break; } } diff --git a/src/gui/accountstate.h b/src/gui/accountstate.h index ea4062735931a..e69f71e87838c 100644 --- a/src/gui/accountstate.h +++ b/src/gui/accountstate.h @@ -82,7 +82,10 @@ class AccountState : public QObject, public QSharedData ConfigurationError, /// We are currently asking the user for credentials - AskingCredentials + AskingCredentials, + + /// Need to sign terms of service by going to web UI + NeedToSignTermsOfService, }; /// The actual current connectivity status. @@ -198,6 +201,7 @@ public slots: void hasFetchedNavigationApps(); void statusChanged(); void desktopNotificationsAllowedChanged(); + void termsOfServiceChanged(OCC::AccountPtr account); protected Q_SLOTS: void slotConnectionValidatorResult(OCC::ConnectionValidator::Status status, const QStringList &errors); diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 1ed8ee15bf57d..9cb0a28de26c6 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -588,6 +588,8 @@ void Application::slotAccountStateAdded(AccountState *accountState) _gui.data(), &ownCloudGui::slotAccountStateChanged); connect(accountState->account().data(), &Account::serverVersionChanged, _gui.data(), &ownCloudGui::slotTrayMessageIfServerUnsupported); + connect(accountState, &AccountState::termsOfServiceChanged, + _gui.data(), &ownCloudGui::slotNeedToAcceptTermsOfService); connect(accountState, &AccountState::stateChanged, _folderManager.data(), &FolderMan::slotAccountStateChanged); connect(accountState->account().data(), &Account::serverVersionChanged, diff --git a/src/gui/connectionvalidator.cpp b/src/gui/connectionvalidator.cpp index e39d523a48bd0..526f1fb7d3cbd 100644 --- a/src/gui/connectionvalidator.cpp +++ b/src/gui/connectionvalidator.cpp @@ -267,7 +267,20 @@ void ConnectionValidator::slotCapabilitiesRecieved(const QJsonDocument &json) QString directEditingETag = caps["files"].toObject()["directEditing"].toObject()["etag"].toString(); _account->fetchDirectEditors(directEditingURL, directEditingETag); - fetchUser(); + checkServerTermsOfService(); +} + +void ConnectionValidator::checkServerTermsOfService() +{ + // The main flow now needs the capabilities + auto *job = new JsonApiJob(_account, QLatin1String("ocs/v2.php/apps/terms_of_service/terms"), this); + job->setTimeout(timeoutToUseMsec); + QObject::connect(job, &JsonApiJob::jsonReceived, this, &ConnectionValidator::slotServerTermsOfServiceRecieved); + QObject::connect(job, &JsonApiJob::networkError, this, [] (QNetworkReply *reply) + { + qCInfo(lcConnectionValidator()) << "network error" << reply->error(); + }); + job->start(); } void ConnectionValidator::fetchUser() @@ -321,6 +334,22 @@ void ConnectionValidator::slotUserFetched(UserInfo *userInfo) #endif } +void ConnectionValidator::slotServerTermsOfServiceRecieved(const QJsonDocument &reply) +{ + qCDebug(lcConnectionValidator) << "Terms of service status" << reply; + + if (reply.object().contains("ocs")) { + const auto hasSigned = reply.object().value("ocs").toObject().value("data").toObject().value("hasSigned").toBool(false); + + if (!hasSigned) { + reportResult(NeedToSignTermsOfService); + return; + } + } + + fetchUser(); +} + #ifndef TOKEN_AUTH_ONLY void ConnectionValidator::reportConnected() { reportResult(Connected); diff --git a/src/gui/connectionvalidator.h b/src/gui/connectionvalidator.h index 4b7193b0c8004..99e2b3d9bb222 100644 --- a/src/gui/connectionvalidator.h +++ b/src/gui/connectionvalidator.h @@ -95,7 +95,8 @@ class ConnectionValidator : public QObject StatusRedirect, // 204 URL received one of redirect HTTP codes (301-307), possibly a captive portal ServiceUnavailable, // 503 on authed request MaintenanceMode, // maintenance enabled in status.php - Timeout // actually also used for other errors on the authed request + Timeout, // actually also used for other errors on the authed request + NeedToSignTermsOfService, }; Q_ENUM(Status); @@ -129,6 +130,7 @@ protected slots: void slotCapabilitiesRecieved(const QJsonDocument &); void slotUserFetched(OCC::UserInfo *userInfo); + void slotServerTermsOfServiceRecieved(const QJsonDocument &reply); private: #ifndef TOKEN_AUTH_ONLY @@ -136,6 +138,7 @@ protected slots: #endif void reportResult(Status status); void checkServerCapabilities(); + void checkServerTermsOfService(); void fetchUser(); /** Sets the account's server version diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index afe3cf193ef80..d5742725c4dd3 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -92,6 +92,12 @@ Folder::Folder(const FolderDefinition &definition, if (!reloadExcludes()) qCWarning(lcFolder, "Could not read system exclude file"); + connect(_accountState.data(), &AccountState::termsOfServiceChanged, + this, [this] () + { + setSyncPaused(_accountState->state() == AccountState::NeedToSignTermsOfService); + }); + connect(_accountState.data(), &AccountState::isConnectedChanged, this, &Folder::canSyncChanged); connect(_engine.data(), &SyncEngine::rootEtag, this, &Folder::etagRetrievedFromSyncEngine); diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index e6e48416790aa..7f439f42639b1 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -267,6 +267,16 @@ void ownCloudGui::slotTrayMessageIfServerUnsupported(Account *account) } } +void ownCloudGui::slotNeedToAcceptTermsOfService(OCC::AccountPtr account) +{ + slotShowTrayMessage( + tr("Terms of service"), + tr("Your account %1 requires you to accept the terms of service of your server. " + "You will be redirected to %2 to acknowledge that you have read it and agrees with it.") + .arg(account->displayName(), account->url().toString())); + QDesktopServices::openUrl(account->url()); +} + void ownCloudGui::slotComputeOverallSyncStatus() { bool allSignedOut = true; diff --git a/src/gui/owncloudgui.h b/src/gui/owncloudgui.h index 8315fe228caa6..1cfc44876d525 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -94,7 +94,7 @@ public slots: void slotOpenPath(const QString &path); void slotAccountStateChanged(); void slotTrayMessageIfServerUnsupported(OCC::Account *account); - + void slotNeedToAcceptTermsOfService(OCC::AccountPtr account); /** * Open a share dialog for a file or folder.