Skip to content

Commit

Permalink
content access denied error during discovery: verify server access
Browse files Browse the repository at this point in the history
will trigger a check of the server connectivity in case of content
access denied reporting when listing folders during discovery

should allow discovering early that terms of service need to be signed

Signed-off-by: Matthieu Gallien <[email protected]>
  • Loading branch information
mgallien authored and backportbot[bot] committed Oct 22, 2024
1 parent 28aca7f commit 736d2c3
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 28 deletions.
15 changes: 12 additions & 3 deletions src/gui/accountstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ AccountState::AccountState(const AccountPtr &account)
, _state(AccountState::Disconnected)
, _connectionStatus(ConnectionValidator::Undefined)
, _waitingForNewCredentials(false)
, _termsOfServiceChecker(_account)
, _maintenanceToConnectedDelay(60000 + (QRandomGenerator::global()->generate() % (4 * 60000))) // 1-5min delay
, _remoteWipe(new RemoteWipe(_account))
, _isDesktopNotificationsAllowed(true)
Expand All @@ -64,10 +65,18 @@ AccountState::AccountState(const AccountPtr &account)
this, &AccountState::slotPushNotificationsReady);
connect(account.data(), &Account::serverUserStatusChanged, this,
&AccountState::slotServerUserStatusChanged);
connect(&_termsOfServiceChecker, &TermsOfServiceChecker::done,
this, [this] ()
{
if (_termsOfServiceChecker.needToSign()) {
slotConnectionValidatorResult(ConnectionValidator::NeedToSignTermsOfService, {});
}
});
connect(account.data(), &Account::termsOfServiceNeedToBeChecked,
this, [this] () {
checkConnectivity();
});
this, [this] ()
{
_termsOfServiceChecker.start();
});

connect(this, &AccountState::isConnectedChanged, [=]{
// Get the Apps available on the server if we're now connected.
Expand Down
1 change: 1 addition & 0 deletions src/gui/accountstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ private Q_SLOTS:
bool _waitingForNewCredentials = false;
QDateTime _timeOfLastETagCheck;
QPointer<ConnectionValidator> _connectionValidator;
TermsOfServiceChecker _termsOfServiceChecker;
QByteArray _notificationsEtagResponseHeader;
QByteArray _navigationAppsEtagResponseHeader;

Expand Down
91 changes: 68 additions & 23 deletions src/gui/connectionvalidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ ConnectionValidator::ConnectionValidator(AccountStatePtr accountState, const QSt
, _previousErrors(previousErrors)
, _accountState(accountState)
, _account(accountState->account())
, _termsOfServiceChecker(_account)
{
connect(&_termsOfServiceChecker, &TermsOfServiceChecker::done,
this, &ConnectionValidator::termsOfServiceCheckDone);
}

void ConnectionValidator::checkServerAndAuth()
Expand Down Expand Up @@ -270,19 +273,6 @@ void ConnectionValidator::slotCapabilitiesRecieved(const QJsonDocument &json)
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()
{
auto *userInfo = new UserInfo(_accountState.data(), true, true, this);
Expand Down Expand Up @@ -317,6 +307,11 @@ bool ConnectionValidator::setAndCheckServerVersion(const QString &version)
return true;
}

void ConnectionValidator::checkServerTermsOfService()
{
_termsOfServiceChecker.start();
}

void ConnectionValidator::slotUserFetched(UserInfo *userInfo)
{
if(userInfo) {
Expand All @@ -332,17 +327,11 @@ void ConnectionValidator::slotUserFetched(UserInfo *userInfo)
#endif
}

void ConnectionValidator::slotServerTermsOfServiceRecieved(const QJsonDocument &reply)
void ConnectionValidator::termsOfServiceCheckDone()
{
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;
}
if (_termsOfServiceChecker.needToSign()) {
reportResult(NeedToSignTermsOfService);
return;
}

fetchUser();
Expand All @@ -366,4 +355,60 @@ void ConnectionValidator::reportResult(Status status)
deleteLater();
}

TermsOfServiceChecker::TermsOfServiceChecker(AccountPtr account, QObject *parent)
: QObject(parent)
, _account(account)
{
}

TermsOfServiceChecker::TermsOfServiceChecker(QObject *parent)
: QObject(parent)
{
}

bool TermsOfServiceChecker::needToSign() const
{
return _needToSign;
}

void TermsOfServiceChecker::start()
{
checkServerTermsOfService();
}

void TermsOfServiceChecker::slotServerTermsOfServiceRecieved(const QJsonDocument &reply)
{
qCDebug(lcConnectionValidator) << "Terms of service status" << reply;

if (reply.object().contains("ocs")) {
const auto needToSign = !reply.object().value("ocs").toObject().value("data").toObject().value("hasSigned").toBool(false);
if (needToSign != _needToSign) {
_needToSign = needToSign;
emit needToSignChanged();
}
} else if (_needToSign) {
_needToSign = false;
emit needToSignChanged();
}

emit done();
}

void TermsOfServiceChecker::checkServerTermsOfService()
{
if (!_account) {
emit done();
}

// 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, &TermsOfServiceChecker::slotServerTermsOfServiceRecieved);
QObject::connect(job, &JsonApiJob::networkError, this, [] (QNetworkReply *reply)
{
qCInfo(lcConnectionValidator()) << "network error" << reply->error();
});
job->start();
}

} // namespace OCC
38 changes: 36 additions & 2 deletions src/gui/connectionvalidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,37 @@ namespace OCC {

class UserInfo;

class TermsOfServiceChecker : public QObject
{
Q_OBJECT

Q_PROPERTY(bool needToSign READ needToSign NOTIFY needToSignChanged FINAL)
public:
explicit TermsOfServiceChecker(AccountPtr account,
QObject *parent = nullptr);

explicit TermsOfServiceChecker(QObject *parent = nullptr);

[[nodiscard]] bool needToSign() const;

public slots:
void start();

signals:
void needToSignChanged();

void done();

private slots:
void slotServerTermsOfServiceRecieved(const QJsonDocument &reply);

private:
void checkServerTermsOfService();

AccountPtr _account;
bool _needToSign = false;
};

class ConnectionValidator : public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -130,15 +161,15 @@ protected slots:

void slotCapabilitiesRecieved(const QJsonDocument &);
void slotUserFetched(OCC::UserInfo *userInfo);
void slotServerTermsOfServiceRecieved(const QJsonDocument &reply);

void termsOfServiceCheckDone();

private:
#ifndef TOKEN_AUTH_ONLY
void reportConnected();
#endif
void reportResult(Status status);
void checkServerCapabilities();
void checkServerTermsOfService();
void fetchUser();

/** Sets the account's server version
Expand All @@ -147,10 +178,13 @@ protected slots:
*/
bool setAndCheckServerVersion(const QString &version);

void checkServerTermsOfService();

const QStringList _previousErrors;
QStringList _errors;
AccountStatePtr _accountState;
AccountPtr _account;
TermsOfServiceChecker _termsOfServiceChecker;
bool _isCheckingServerAndAuth = false;
};
}
Expand Down

0 comments on commit 736d2c3

Please sign in to comment.