Skip to content

[DC-49] feature: start removing support for OC10 #12167

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

Merged
merged 19 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
63619db
removed DetermineAuthTypeJobFactory and replaced it with synchronous …
modSpike May 26, 2025
7814728
removed support for legacy web finger
modSpike May 26, 2025
3f519b0
reverted an incorrect change introduced in the last commit (removal o…
modSpike May 27, 2025
a4b3012
first pass to remove the basic http authentication support, including…
modSpike May 28, 2025
cfb84d4
Moved the decls of AuthenticationType and DontAddCredentialsAttribute…
modSpike Jun 2, 2025
5eb42a0
remove the decl for DetermineAuthTypeJob from the header
modSpike Jun 2, 2025
369724e
Merge branch 'master' into work/DC-49
modSpike Jun 2, 2025
f84a0e5
removed last traces of AuthenticationType::Basic
modSpike Jun 2, 2025
b7f2b9f
more general cleanup
modSpike Jun 3, 2025
d7dc623
added new FetchCapabilitiesAdapter
modSpike Jun 4, 2025
0326d73
just added a todo related to a sneaky oc10 thing that we should remove
modSpike Jun 4, 2025
6c4e5d0
Merge branch 'master' into work/DC-49
modSpike Jun 4, 2025
21d0217
fixed capabilities check for webfinger cases
modSpike Jun 5, 2025
1ac36f3
Merge branch 'work/DC-49' of github.com:owncloud/client into work/DC-49
modSpike Jun 5, 2025
17258ed
Merge branch 'master' into work/DC-49
modSpike Jun 5, 2025
b20e714
added missing check for success on retrieving the capabilities
modSpike Jun 5, 2025
f94074c
Merge branch 'master' into work/DC-49
modSpike Jun 6, 2025
76e4bbc
added missing copyrights
modSpike Jun 6, 2025
d9cabab
Merge branch 'master' into work/DC-49
modSpike Jun 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ ecm_add_qml_module(owncloudGui
qml/FolderDelegate.qml
qml/FolderError.qml

qml/credentials/BasicAuthCredentials.qml
qml/credentials/Credentials.qml
qml/credentials/OAuthCredentials.qml

Expand Down
1 change: 1 addition & 0 deletions src/gui/accountstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ void AccountState::setState(State state)
// update capabilities and fetch relevant settings
_fetchCapabilitiesJob = new FetchServerSettingsJob(account(), this);
connect(_fetchCapabilitiesJob.get(), &FetchServerSettingsJob::finishedSignal, this, [oldState, this] {
// Lisa todo: I do not understand this logic at all - review it
if (oldState == Connected || _state == Connected) {
_fetchCapabilitiesJob.clear();
Q_EMIT isConnectedChanged();
Expand Down
1 change: 1 addition & 0 deletions src/gui/connectionvalidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ void ConnectionValidator::checkAuthentication()
job->start();
}

// Lisa todo: I hit this once and nothing happened in the gui?!
void ConnectionValidator::slotAuthFailed()
{
auto job = qobject_cast<PropfindJob *>(sender());
Expand Down
68 changes: 7 additions & 61 deletions src/gui/creds/httpcredentialsgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "account.h"
#include "accountmodalwidget.h"
#include "application.h"
#include "common/asserts.h"
#include "creds/qmlcredentials.h"
#include "gui/accountsettings.h"
#include "networkjobs.h"
Expand All @@ -32,13 +31,10 @@ namespace OCC {

Q_LOGGING_CATEGORY(lcHttpCredentialsGui, "sync.credentials.http.gui", QtInfoMsg)

HttpCredentialsGui::HttpCredentialsGui(const QString &loginUser, const QString &password)
: HttpCredentials(DetermineAuthTypeJob::AuthType::Basic, loginUser, password)
{
}

// with oauth the account builder actually passes the token in place of the password.
HttpCredentialsGui::HttpCredentialsGui(const QString &davUser, const QString &password, const QString &refreshToken)
: HttpCredentials(DetermineAuthTypeJob::AuthType::OAuth, davUser, password)
: HttpCredentials(OCC::AuthenticationType::OAuth, davUser, password)
{
_refreshToken = refreshToken;
}
Expand All @@ -52,21 +48,6 @@ void HttpCredentialsGui::askFromUser()
QTimer::singleShot(0, this, [this] {
if (isUsingOAuth()) {
startOAuth();
} else {
// First, we will check what kind of auth we need.
auto job = new DetermineAuthTypeJob(_account->sharedFromThis(), this);
QObject::connect(job, &DetermineAuthTypeJob::authType, this, [this](DetermineAuthTypeJob::AuthType type) {
_authType = type;
if (type == DetermineAuthTypeJob::AuthType::OAuth) {
startOAuth();
} else if (type == DetermineAuthTypeJob::AuthType::Basic) {
showDialog();
} else {
qCWarning(lcHttpCredentialsGui) << "Bad http auth type:" << type;
Q_EMIT fetched();
}
});
job->start();
}
});
}
Expand All @@ -76,13 +57,9 @@ void HttpCredentialsGui::asyncAuthResult(OAuth::Result r, const QString &token,
_asyncAuth.reset();
switch (r) {
case OAuth::NotSupported:
if (_modalWidget) {
_modalWidget->deleteLater();
_modalWidget.clear();
}
// show basic auth dialog for historic reasons
showDialog();
return;
// also should not happen after initial setup?
Q_ASSERT(false);
[[fallthrough]];
case OAuth::ErrorInsecureUrl:
// should not happen after the initial setup
Q_ASSERT(false);
Expand All @@ -102,44 +79,13 @@ void HttpCredentialsGui::asyncAuthResult(OAuth::Result r, const QString &token,
Q_EMIT fetched();
}

void HttpCredentialsGui::showDialog()
{
if (_modalWidget) {
return;
}

auto basicCredentials = new QmlBasicCredentials(_account->url(), _account->davDisplayName(), this);
basicCredentials->setReadOnlyName(user());
_modalWidget = new AccountModalWidget(tr("Login required"), QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/qml/credentials/BasicAuthCredentials.qml")),
basicCredentials, ocApp()->gui()->settingsDialog());
connect(basicCredentials, &QmlBasicCredentials::logOutRequested, _modalWidget, [basicCredentials, this] {
Q_EMIT requestLogout();
Q_EMIT fetched();
_modalWidget->reject();
basicCredentials->deleteLater();
});
connect(basicCredentials, &QmlBasicCredentials::loginRequested, _modalWidget, [basicCredentials, this] {
_password = basicCredentials->password();
basicCredentials->deleteLater();
_refreshToken.clear();
_ready = true;
persist();

Q_EMIT fetched();
_modalWidget->accept();
});


ocApp()->gui()->settingsDialog()->accountSettings(_account)->addModalWidget(_modalWidget);
}

void HttpCredentialsGui::startOAuth()
{
qCDebug(lcHttpCredentialsGui) << "showing modal dialog asking user to log in again via OAuth2";
if (_asyncAuth) {
return;
}
if (!OC_ENSURE_NOT(_modalWidget)) {
if (_modalWidget) {
_modalWidget->deleteLater();
}
_asyncAuth.reset(new AccountBasedOAuth(_account->sharedFromThis(), this));
Expand All @@ -153,7 +99,7 @@ void HttpCredentialsGui::startOAuth()
_modalWidget->reject();
_modalWidget.clear();
_asyncAuth.reset();
requestLogout();
Q_EMIT requestLogout();
});
connect(oauthCredentials, &QmlOAuthCredentials::requestRestart, this, [this] {
_modalWidget->reject();
Expand Down
6 changes: 3 additions & 3 deletions src/gui/creds/httpcredentialsgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,18 @@ class HttpCredentialsGui : public HttpCredentials
public:
HttpCredentialsGui() = default;

HttpCredentialsGui(const QString &loginUser, const QString &password);

HttpCredentialsGui(const QString &davUser, const QString &password, const QString &refreshToken);

/**
* This will query the server and either uses OAuth via _asyncAuth->start()
* or call showDialog to ask the password
*/
// todo: #18 most of this impl will go away, consider renaming it if it's even needed
void askFromUser() override;


private Q_SLOTS:
void asyncAuthResult(OAuth::Result, const QString &accessToken, const QString &refreshToken);
void showDialog();

Q_SIGNALS:
void oAuthLoginAccepted();
Expand All @@ -56,6 +54,8 @@ private Q_SLOTS:
void startOAuth();

QScopedPointer<AccountBasedOAuth, QScopedPointerObjectDeleteLater<AccountBasedOAuth>> _asyncAuth;
// we need to keep this as it hosts the authentication dialog for oauth via web interface
// -> the one that has "open web browser", "copy link" and "log out" options
QPointer<AccountModalWidget> _modalWidget;
};

Expand Down
1 change: 1 addition & 0 deletions src/gui/fetchserversettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void FetchServerSettingsJob::start()
job->data().value(QStringLiteral("ocs")).toObject().value(QStringLiteral("data")).toObject().value(QStringLiteral("capabilities")).toObject();
qCInfo(lcfetchserversettings) << "Server capabilities" << caps;
if (job->ocsSuccess()) {
// todo: #23 - this comment is important relative to that review
// Record that the server supports HTTP/2
// Actual decision if we should use HTTP/2 is done in AccessManager::createRequest
// TODO: http2 support is currently disabled in the client code
Expand Down
1 change: 1 addition & 0 deletions src/gui/folderwizard/folderwizard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ FolderWizardPrivate::FolderWizardPrivate(FolderWizard *q, const AccountStatePtr

q->setPage(FolderWizard::Page_Source, _folderWizardSourcePage);

// apparently also oc10 only per deprecation message on singleSyncFolder()
if (!_account->supportsSpaces() && !Theme::instance()->singleSyncFolder()) {
_folderWizardTargetPage = new FolderWizardRemotePath(this);
q->setPage(FolderWizard::Page_Target, _folderWizardTargetPage);
Expand Down
2 changes: 2 additions & 0 deletions src/gui/networkadapters/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ target_sources(owncloudGui PRIVATE
resolveurladapter.cpp
webfingerlookupadapter.cpp
discoverwebfingerserviceadapter.cpp
determineauthtypeadapter.cpp
fetchcapabilitiesadapter.cpp
)

79 changes: 79 additions & 0 deletions src/gui/networkadapters/determineauthtypeadapter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (C) Lisa Reese <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

#include "determineauthtypeadapter.h"

#include "abstractcorejob.h"
#include "common/utility.h"
#include "creds/credentialssupport.h"
#include "theme.h"

#include <QEventLoop>
#include <QLoggingCategory>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>

namespace OCC {

Q_LOGGING_CATEGORY(lcDetermineAuthTypeAdapter, "gui.networkadapters.determineauthtypeadapter");

DetermineAuthTypeAdapter::DetermineAuthTypeAdapter(QNetworkAccessManager *nam, const QUrl &url, QObject *parent)
: QObject(parent)
, _nam(nam)
, _url(url)
{
}

DetermineAuthTypeResult DetermineAuthTypeAdapter::getResult()
{
DetermineAuthTypeResult res;
if (!_nam)
return res;

// we explicitly use a legacy dav path here
QNetworkRequest req = AbstractCoreJobFactory::makeRequest(Utility::concatUrlPath(_url, Theme::instance()->webDavPath()));

req.setAttribute(DontAddCredentialsAttribute, true);
req.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);

QEventLoop waitLoop;
QNetworkReply *reply = _nam->sendCustomRequest(req, "PROPFIND");
connect(reply, &QNetworkReply::finished, &waitLoop, &QEventLoop::quit);
waitLoop.exec();

if (reply->error() == QNetworkReply::AuthenticationRequiredError) {
// the header key is case insensitive per debug testing
const QByteArray rawHeader = reply->rawHeader(QByteArrayLiteral("www-authenticate")).toLower();

if (rawHeader.contains(QByteArrayLiteral("bearer "))) {
res.type = AuthenticationType::OAuth;
} else {
res.error = tr("Server does not support OAuth");
if (rawHeader.isEmpty()) {
qCWarning(lcDetermineAuthTypeAdapter) << "Did not receive WWW-Authenticate reply to auth-test PROPFIND";
} else {
qCWarning(lcDetermineAuthTypeAdapter) << "Did not receive bearer in WWW-Authenticate reply to auth-test PROPFIND";
}
}
} else if (reply->error() == QNetworkReply::NoError) {
res.error = tr("Server did not ask for authorization");
} else {
res.error = tr("Failed to determine authentication type: %1").arg(reply->errorString());
}

delete reply;
return res;
}
}
64 changes: 64 additions & 0 deletions src/gui/networkadapters/determineauthtypeadapter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (C) Lisa Reese <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

#pragma once

#include "creds/credentialssupport.h"
#include <QObject>
#include <QUrl>

class QNetworkAccessManager;

namespace OCC {

struct DetermineAuthTypeResult
{
QString error;
AuthenticationType type = AuthenticationType::Unknown;
bool success() const { return error.isEmpty(); }
};

/**
* @brief The DetermineAuthTypeAdapter class allows us to validate that a given server URL supports oauth authentication.
* If oauth is not supported, the authentication type will be reported as unknown. It is up to the caller to report an
* error or handle this condition in some responsible manner.
*
* This routine used to identify basic http server authentication as well but the Basic type is obsolete after client 6.0
*
*/
class DetermineAuthTypeAdapter : public QObject
{
Q_OBJECT

public:
/**
* @brief DetermineAuthTypeAdapter
* @param nam the network access manager which will run the request.
* @param url the url for the request.
* @param parent follows the typical QObject parenting scheme, but this param is rarely needed since an instance should normally be
* created on the stack and will naturally destruct when it goes out of scope.
*/
DetermineAuthTypeAdapter(QNetworkAccessManager *nam, const QUrl &url, QObject *parent = nullptr);

/**
* @brief getResult runs the request to determine authentication type synchronously
* @return the relevant data extracted from the reply
*/
DetermineAuthTypeResult getResult();

private:
QNetworkAccessManager *_nam;
QUrl _url;
};
}
7 changes: 5 additions & 2 deletions src/gui/networkadapters/discoverwebfingerserviceadapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ struct DiscoverWebFingerServiceResult
};

/**
* This adapter allows the caller to find a webfinger service synchronously, which is very useful when called from a gui
* because we can't continue until the required values are known.
* This adapter allows the caller to find the href of a webfinger service associated with a given URL. No authentication is
* required for this operation, we are merely checking to see if webfinger is available, and if so, we collect the href
* for future use.
*
* The request is run synchronously, which is very useful when called from a gui because we can't continue until the required values are known.
*
* In future we may also extend the adapter to run in async mode as well, but for now it's not needed.
*
Expand Down
Loading