Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve ToS handling #7856

Merged
merged 8 commits into from
Feb 20, 2025
5 changes: 5 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ set(client_UI_SRCS
wizard/owncloudconnectionmethoddialog.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudsetupnocredspage.ui
wizard/termsofservicecheckwidget.ui
wizard/webview.ui
wizard/welcomepage.ui
)
Expand Down Expand Up @@ -240,6 +241,10 @@ set(client_SRCS
wizard/flow2authwidget.cpp
wizard/owncloudsetuppage.h
wizard/owncloudsetuppage.cpp
wizard/termsofservicecheckwidget.h
wizard/termsofservicecheckwidget.cpp
wizard/termsofservicewizardpage.h
wizard/termsofservicewizardpage.cpp
wizard/owncloudwizardcommon.h
wizard/owncloudwizardcommon.cpp
wizard/owncloudwizard.h
Expand Down
2 changes: 1 addition & 1 deletion src/gui/accountsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ void AccountSettings::slotAccountStateChanged()
Q_UNREACHABLE();
break;
case AccountState::NeedToSignTermsOfService:
showConnectionLabel(tr("You need to accept the terms of service"));
showConnectionLabel(tr("You need to accept the terms of service at %1.").arg(server));
break;
}
} else {
Expand Down
7 changes: 6 additions & 1 deletion src/gui/accountstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,12 @@
return _state == Connected;
}

bool AccountState::needsToSignTermsOfService() const

Check warning on line 225 in src/gui/accountstate.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/accountstate.cpp:225:20 [modernize-use-trailing-return-type]

use a trailing return type for this function
{
return _state == NeedToSignTermsOfService;
}

void AccountState::tagLastSuccessfullETagRequest(const QDateTime &tp)

Check warning on line 230 in src/gui/accountstate.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/accountstate.cpp:230:67 [readability-identifier-length]

parameter name 'tp' is too short, expected at least 3 characters
{
_timeOfLastETagCheck = tp;
}
Expand Down Expand Up @@ -316,7 +321,7 @@
_connectionErrors.clear();
connect(conValidator, &ConnectionValidator::connectionResult,
this, &AccountState::slotConnectionValidatorResult);
if (isConnected()) {
if (isConnected() || needsToSignTermsOfService()) {

Check warning on line 324 in src/gui/accountstate.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/accountstate.cpp:324:5 [bugprone-branch-clone]

if with identical then and else branches
// Use a small authed propfind as a minimal ping when we're
// already connected.
conValidator->checkAuthentication();
Expand Down
2 changes: 2 additions & 0 deletions src/gui/accountstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ class AccountState : public QObject, public QSharedData

bool isConnected() const;

bool needsToSignTermsOfService() const;

/** Returns a new settings object for this account, already in the right groups. */
std::unique_ptr<QSettings> settings();

Expand Down
11 changes: 9 additions & 2 deletions src/gui/connectionvalidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* for more details.
*/

#include <QJsonDocument>

Check failure on line 15 in src/gui/connectionvalidator.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/connectionvalidator.cpp:15:10 [clang-diagnostic-error]

'QJsonDocument' file not found
#include <QJsonObject>
#include <QJsonArray>
#include <QLoggingCategory>
Expand Down Expand Up @@ -221,13 +221,20 @@
stat = CredentialsWrong;

} else if (reply->error() != QNetworkReply::NoError) {
_errors << job->errorStringParsingBody();
QByteArray body;

Check warning on line 224 in src/gui/connectionvalidator.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/connectionvalidator.cpp:224:20 [cppcoreguidelines-init-variables]

variable 'body' is not initialized
_errors << job->errorStringParsingBody(&body);

const int httpStatus =
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (httpStatus == 503) {
_errors.clear();
stat = ServiceUnavailable;
} else if (httpStatus == 403) {
const auto davException = job->errorStringParsingBodyException(body);
if (davException == QStringLiteral(R"(OCA\TermsOfService\TermsNotSignedException)")) {
qCInfo(lcConnectionValidator) << "The terms of service need to be signed";
stat = NeedToSignTermsOfService;
}
}
}

Expand Down Expand Up @@ -383,9 +390,9 @@
if (reply.object().contains("ocs")) {
const auto needToSign = !reply.object().value("ocs").toObject().value("data").toObject().value("hasSigned").toBool(false);
if (needToSign != _needToSign) {
qCInfo(lcConnectionValidator) << "_needToSign" << (_needToSign ? "need to sign" : "no need to sign");
_needToSign = needToSign;
qCInfo(lcConnectionValidator) << "_needToSign" << (_needToSign ? "need to sign" : "no need to sign");
emit needToSignChanged();

Check warning on line 395 in src/gui/connectionvalidator.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/connectionvalidator.cpp:395:18 [modernize-use-trailing-return-type]

use a trailing return type for this function
}
} else if (_needToSign) {
_needToSign = false;
Expand Down
42 changes: 29 additions & 13 deletions src/gui/owncloudsetupwizard.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/owncloudsetupwizard.cpp

File src/gui/owncloudsetupwizard.cpp does not conform to Custom style guidelines. (lines 40, 384)
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
Expand All @@ -13,14 +13,7 @@
* for more details.
*/

#include <QAbstractButton>
#include <QtCore>
#include <QProcess>
#include <QMessageBox>
#include <QDesktopServices>
#include <QApplication>

#include "accessmanager.h"

Check failure on line 16 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:16:10 [clang-diagnostic-error]

'accessmanager.h' file not found
#include "account.h"
#include "accountmanager.h"
#include "clientproxy.h"
Expand All @@ -31,6 +24,7 @@
#include "networkjobs.h"
#include "owncloudgui.h"
#include "owncloudsetupwizard.h"
#include "owncloudpropagator_p.h"
#include "sslerrordialog.h"
#include "wizard/owncloudwizard.h"
#include "wizard/owncloudwizardcommon.h"
Expand All @@ -43,6 +37,13 @@
#include "gui/macOS/fileprovider.h"
#endif

#include <QAbstractButton>
#include <QtCore>
#include <QProcess>
#include <QMessageBox>
#include <QDesktopServices>
#include <QApplication>

namespace OCC {

OwncloudSetupWizard::OwncloudSetupWizard(QObject *parent)
Expand Down Expand Up @@ -362,8 +363,7 @@

_ocWizard->setField(QLatin1String("OCUrl"), url);
_ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2 …")
.arg(Theme::instance()->appNameGUI())
.arg(url));
.arg(Theme::instance()->appNameGUI(), url));

testOwnCloudConnect();
});
Expand All @@ -381,7 +381,22 @@
job->setFollowRedirects(false);
job->setProperties(QList<QByteArray>() << "getlastmodified");
connect(job, &PropfindJob::result, _ocWizard, &OwncloudWizard::successfulStep);
connect(job, &PropfindJob::finishedWithError, this, &OwncloudSetupWizard::slotAuthError);
connect(job, &PropfindJob::finishedWithError, this, [this] (QNetworkReply *reply) -> void {
if (reply && reply->error() == QNetworkReply::ContentAccessDenied) {
// A 403 might indicate that the terms of service need to be signed.
// catch this special case here, fall back to the standard error handler if it's not TOS-related
auto davException = OCC::getExceptionFromReply(reply);
if (!davException.first.isEmpty() && davException.first == QStringLiteral(R"(OCA\TermsOfService\TermsNotSignedException)")) {
// authentication was successful, but the user hasn't signed the terms of service yet. Prompt for that in the next step
qCInfo(lcWizard) << "Terms of service not accepted yet! Will prompt the user in the next step";
_ocWizard->_needsToAcceptTermsOfService = true;
_ocWizard->successfulStep();
return;
}
}
slotAuthError();
});

job->start();
}

Expand Down Expand Up @@ -418,15 +433,16 @@
"\"%1\". The URL is bad, the server is misconfigured.")
.arg(Utility::escape(redirectUrl.toString()));

} else if (reply->error() == QNetworkReply::ContentNotFoundError) {
// A 404 is actually a success: we were authorized to know that the folder does
// not exist. It will be created later...
} else if (reply->error() == QNetworkReply::ContentNotFoundError) {
_ocWizard->successfulStep();
return;

// Provide messages for other errors, such as invalid credentials.
} else if (reply->error() != QNetworkReply::NoError) {
// Provide messages for other errors, such as invalid credentials.

if (!_ocWizard->account()->credentials()->stillValid(reply)) {

Check warning on line 445 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:445:9 [bugprone-branch-clone]

if with identical then and else branches
errorMsg = tr("Access forbidden by server. To verify that you have proper access, "
"<a href=\"%1\">click here</a> to access the service with your browser.")
.arg(Utility::escape(_ocWizard->account()->url().toString()));
Expand All @@ -434,8 +450,8 @@
errorMsg = job->errorStringParsingBody();
}

// Something else went wrong, maybe the response was 200 but with invalid data.
} else {
// Something else went wrong, maybe the response was 200 but with invalid data.
errorMsg = tr("There was an invalid response to an authenticated WebDAV request");
}

Expand Down
4 changes: 3 additions & 1 deletion src/gui/owncloudsetupwizard.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#ifndef OWNCLOUDSETUPWIZARD_H
#define OWNCLOUDSETUPWIZARD_H

#include <QObject>

Check failure on line 18 in src/gui/owncloudsetupwizard.h

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.h:18:10 [clang-diagnostic-error]

'QObject' file not found
#include <QWidget>
#include <QProcess>
#include <QNetworkReply>
Expand All @@ -30,6 +30,7 @@
namespace OCC {

class AccountState;
class TermsOfServiceChecker;

class OwncloudWizard;

Expand All @@ -44,6 +45,7 @@
/** Run the wizard */
static void runWizard(QObject *obj, const char *amember, QWidget *parent = nullptr);
static bool bringWizardToFrontIfVisible();

signals:
// overall dialog close signal.
void ownCloudWizardDone(int);
Expand Down Expand Up @@ -80,7 +82,7 @@
AccountState *applyAccountChanges();
bool checkDowngradeAdvised(QNetworkReply *reply);

OwncloudWizard *_ocWizard;
OwncloudWizard *_ocWizard = nullptr;
QString _initLocalFolder;
QString _remoteFolder;
};
Expand Down
11 changes: 11 additions & 0 deletions src/gui/tray/SyncStatus.qml
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,15 @@ RowLayout {
enabled: visible
onClicked: NC.Systray.createResolveConflictsDialog(activityModel.allConflicts);
}

Button {
Layout.rightMargin: Style.trayHorizontalMargin

text: qsTr("Open browser")

visible: NC.UserModel.currentUser.needsToSignTermsOfService
enabled: visible

onClicked: NC.UserModel.openCurrentAccountServer()
}
}
9 changes: 9 additions & 0 deletions src/gui/tray/syncstatussummary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "syncstatussummary.h"
#include "accountfwd.h"
#include "accountstate.h"
#include "folderman.h"
#include "navigationpanehelper.h"
#include "networkjobs.h"
Expand Down Expand Up @@ -128,6 +129,14 @@ void SyncStatusSummary::clearFolderErrors()
void SyncStatusSummary::setSyncStateForFolder(const Folder *folder)
{
if (_accountState && !_accountState->isConnected()) {
setSyncing(false);
setTotalFiles(0);
setSyncStatusString(tr("Offline"));
setSyncStatusDetailString("");
if (_accountState->state() == AccountState::NeedToSignTermsOfService) {
setSyncStatusDetailString(tr("You need to accept the terms of service"));
}
setSyncIcon(Theme::instance()->folderOffline());
return;
}

Expand Down
5 changes: 5 additions & 0 deletions src/gui/tray/usermodel.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "notificationhandler.h"

Check notice on line 1 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/tray/usermodel.cpp

File src/gui/tray/usermodel.cpp does not conform to Custom style guidelines. (lines 1136)
#include "usermodel.h"
#include "common/filesystembase.h"

Expand Down Expand Up @@ -1130,6 +1130,11 @@
return (_account->connectionStatus() == AccountState::ConnectionStatus::Connected);
}

bool User::needsToSignTermsOfService() const

Check warning on line 1133 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:1133:12 [modernize-use-trailing-return-type]

use a trailing return type for this function
{
return _account->connectionStatus() == AccountState::ConnectionStatus::NeedToSignTermsOfService;
}


bool User::isDesktopNotificationsAllowed() const
{
Expand Down
2 changes: 2 additions & 0 deletions src/gui/tray/usermodel.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef USERMODEL_H
#define USERMODEL_H

#include <QAbstractListModel>

Check failure on line 4 in src/gui/tray/usermodel.h

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.h:4:10 [clang-diagnostic-error]

'QAbstractListModel' file not found
#include <QImage>
#include <QDateTime>
#include <QStringList>
Expand Down Expand Up @@ -61,6 +61,7 @@
Q_PROPERTY(QString featuredAppAccessibleName READ featuredAppAccessibleName NOTIFY featuredAppChanged)
Q_PROPERTY(QString avatar READ avatarUrl NOTIFY avatarChanged)
Q_PROPERTY(bool isConnected READ isConnected NOTIFY accountStateChanged)
Q_PROPERTY(bool needsToSignTermsOfService READ needsToSignTermsOfService NOTIFY accountStateChanged)
Q_PROPERTY(UnifiedSearchResultsListModel* unifiedSearchResultsListModel READ getUnifiedSearchResultsListModel CONSTANT)
Q_PROPERTY(QVariantList groupFolders READ groupFolders NOTIFY groupFoldersChanged)

Expand All @@ -71,6 +72,7 @@
[[nodiscard]] AccountStatePtr accountState() const;

[[nodiscard]] bool isConnected() const;
[[nodiscard]] bool needsToSignTermsOfService() const;
[[nodiscard]] bool isCurrentUser() const;
void setCurrentUser(const bool &isCurrent);
[[nodiscard]] Folder *getFolder() const;
Expand Down
6 changes: 6 additions & 0 deletions src/gui/wizard/flow2authcredspage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* for more details.
*/

#include <QVariant>

Check failure on line 16 in src/gui/wizard/flow2authcredspage.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/flow2authcredspage.cpp:16:10 [clang-diagnostic-error]

'QVariant' file not found
#include <QVBoxLayout>

#include "flow2authcredspage.h"
Expand Down Expand Up @@ -104,6 +104,12 @@

int Flow2AuthCredsPage::nextId() const
{
const auto ocWizard = qobject_cast<OwncloudWizard *>(wizard());
Q_ASSERT(ocWizard);
if (ocWizard->needsToAcceptTermsOfService()) {
return WizardCommon::Page_TermsOfService;
}

return WizardCommon::Page_AdvancedSetup;
}

Expand Down
10 changes: 10 additions & 0 deletions src/gui/wizard/owncloudadvancedsetuppage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* for more details.
*/

#include <QDir>

Check failure on line 16 in src/gui/wizard/owncloudadvancedsetuppage.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/owncloudadvancedsetuppage.cpp:16:10 [clang-diagnostic-error]

'QDir' file not found
#include <QFileDialog>
#include <QUrl>
#include <QTimer>
Expand Down Expand Up @@ -196,6 +196,7 @@
quotaJob->setProperties(QList<QByteArray>() << "http://owncloud.org/ns:size");

connect(quotaJob, &PropfindJob::result, this, &OwncloudAdvancedSetupPage::slotQuotaRetrieved);
connect(quotaJob, &PropfindJob::finishedWithError, this, &OwncloudAdvancedSetupPage::slotQuotaRetrievedWithError);
quotaJob->start();

if (Theme::instance()->wizardSelectiveSyncDefaultNothing()) {
Expand Down Expand Up @@ -576,6 +577,15 @@
updateStatus();
}

void OwncloudAdvancedSetupPage::slotQuotaRetrievedWithError(QNetworkReply *reply)
{
Q_UNUSED(reply)
_rSize = -1;
_ui.lSyncEverythingSizeLabel->setText({});

updateStatus();
}

qint64 OwncloudAdvancedSetupPage::availableLocalSpace() const
{
QString localDir = localFolder();
Expand Down
2 changes: 2 additions & 0 deletions src/gui/wizard/owncloudadvancedsetuppage.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
#ifndef MIRALL_OWNCLOUD_ADVANCED_SETUP_PAGE_H
#define MIRALL_OWNCLOUD_ADVANCED_SETUP_PAGE_H

#include <QWizard>

Check failure on line 19 in src/gui/wizard/owncloudadvancedsetuppage.h

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/owncloudadvancedsetuppage.h:19:10 [clang-diagnostic-error]

'QWizard' file not found

#include "wizard/owncloudwizardcommon.h"
#include "ui_owncloudadvancedsetuppage.h"
#include "elidedlabel.h"

class QProgressIndicator;
class QNetworkReply;

Check warning on line 26 in src/gui/wizard/owncloudadvancedsetuppage.h

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/owncloudadvancedsetuppage.h:26:7 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'QNetworkReply' is non-const and globally accessible, consider making it const

namespace OCC {

Expand Down Expand Up @@ -63,6 +64,7 @@
void slotSelectiveSyncClicked();
void slotVirtualFileSyncClicked();
void slotQuotaRetrieved(const QVariantMap &result);
void slotQuotaRetrievedWithError(QNetworkReply *reply);

private:
void setRadioChecked(QRadioButton *radio);
Expand Down
6 changes: 6 additions & 0 deletions src/gui/wizard/owncloudhttpcredspage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* for more details.
*/

#include "QProgressIndicator.h"

Check failure on line 16 in src/gui/wizard/owncloudhttpcredspage.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/owncloudhttpcredspage.cpp:16:10 [clang-diagnostic-error]

'QProgressIndicator.h' file not found

#include "creds/httpcredentialsgui.h"
#include "theme.h"
Expand Down Expand Up @@ -153,6 +153,12 @@

int OwncloudHttpCredsPage::nextId() const
{
const auto ocWizard = qobject_cast<OwncloudWizard *>(wizard());
Q_ASSERT(ocWizard);
if (ocWizard->needsToAcceptTermsOfService()) {
return WizardCommon::Page_TermsOfService;
}

return WizardCommon::Page_AdvancedSetup;
}

Expand Down
Loading
Loading