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

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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