diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 6446876cd..b882c1562 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -1320,6 +1320,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 d1a095779..59f26fe7c 100644 --- a/src/gui/accountstate.cpp +++ b/src/gui/accountstate.cpp @@ -64,6 +64,10 @@ AccountState::AccountState(const AccountPtr &account) this, &AccountState::slotPushNotificationsReady); connect(account.data(), &Account::serverUserStatusChanged, this, &AccountState::slotServerUserStatusChanged); + connect(account.data(), &Account::termsOfServiceNeedToBeChecked, + this, [this] () { + checkConnectivity(); + }); connect(this, &AccountState::isConnectedChanged, [=]{ // Get the Apps available on the server if we're now connected. @@ -159,6 +163,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"); } @@ -346,6 +352,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 @@ -424,6 +436,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 77caa1b40..019b96d70 100644 --- a/src/gui/accountstate.h +++ b/src/gui/accountstate.h @@ -82,7 +82,10 @@ public: 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. @@ -192,6 +195,7 @@ signals: 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 171acc75c..9dff3dcbf 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -627,6 +627,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 87473c2ed..3d7c974df 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() @@ -319,6 +332,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 ecff3b98b..788a30da2 100644 --- a/src/gui/connectionvalidator.h +++ b/src/gui/connectionvalidator.h @@ -95,7 +95,8 @@ public: 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 @@ private: #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 066d655c4..e35be0168 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -93,6 +93,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 60138a494..abd1b6ec9 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -285,6 +285,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 8315fe228..1cfc44876 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. diff --git a/src/libsync/account.h b/src/libsync/account.h index 4afd9f654..92a132ef6 100644 --- a/src/libsync/account.h +++ b/src/libsync/account.h @@ -464,6 +464,7 @@ signals: void downloadLimitSettingChanged(); void uploadLimitChanged(); void downloadLimitChanged(); + void termsOfServiceNeedToBeChecked(); protected Q_SLOTS: void slotCredentialsFetched(); diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index 38e4a424c..4cb604b9a 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -652,6 +652,10 @@ void DiscoverySingleDirectoryJob::lsJobFinishedWithErrorSlot(QNetworkReply *r) msg = tr("Server error: PROPFIND reply is not XML formatted!"); } + if (r->error() == QNetworkReply::ContentAccessDenied) { + emit _account->termsOfServiceNeedToBeChecked(); + } + emit finished(HttpError{ httpCode, msg }); deleteLater(); }