OAuth: Use redirectable jobs for oauth token management

This commit is contained in:
Christian Kamm 2017-09-08 16:43:59 +02:00 committed by Roeland Jago Douma
parent 0e8ce9c3db
commit ce51ea34b9
No known key found for this signature in database
GPG key ID: F941078878347C0C
8 changed files with 84 additions and 12 deletions

View file

@ -20,6 +20,7 @@
#include <QJsonObject>
#include <QJsonDocument>
#include "theme.h"
#include "networkjobs.h"
namespace OCC {
@ -82,9 +83,8 @@ void OAuth::start()
requestToken.setPassword(Theme::instance()->oauthClientSecret());
QNetworkRequest req;
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
auto reply = _account->sendRequest("POST", requestToken, req);
QTimer::singleShot(30 * 1000, reply, &QNetworkReply::abort);
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, socket] {
auto job = _account->sendRequest("POST", requestToken, req);
QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, socket](QNetworkReply *reply) {
auto jsonData = reply->readAll();
QJsonParseError jsonParseError;
QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();

View file

@ -120,15 +120,20 @@ QNetworkReply *AbstractNetworkJob::addTimer(QNetworkReply *reply)
QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb, const QUrl &url,
QNetworkRequest req, QIODevice *requestBody)
{
auto reply = _account->sendRequest(verb, url, req, requestBody);
auto reply = _account->sendRawRequest(verb, url, req, requestBody);
_requestBody = requestBody;
if (_requestBody) {
_requestBody->setParent(reply);
}
adoptRequest(reply);
return reply;
}
void AbstractNetworkJob::adoptRequest(QNetworkReply *reply)
{
addTimer(reply);
setReply(reply);
setupConnections(reply);
return reply;
}
QUrl AbstractNetworkJob::makeAccountUrl(const QString &relativePath) const

View file

@ -126,6 +126,13 @@ protected:
QNetworkRequest req = QNetworkRequest(),
QIODevice *requestBody = 0);
/** Makes this job drive a pre-made QNetworkReply
*
* This reply cannot have a QIODevice request body because we can't get
* at it and thus not resend it in case of redirects.
*/
void adoptRequest(QNetworkReply *reply);
/// Creates a url for the account from a relative path
QUrl makeAccountUrl(const QString &relativePath) const;

View file

@ -226,7 +226,7 @@ QSharedPointer<QNetworkAccessManager> Account::sharedNetworkAccessManager()
return _am;
}
QNetworkReply *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data)
QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data)
{
req.setUrl(url);
req.setSslConfiguration(this->getOrCreateSslConfig());
@ -244,6 +244,13 @@ QNetworkReply *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNe
return _am->sendCustomRequest(req, verb, data);
}
SimpleNetworkJob *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data)
{
auto job = new SimpleNetworkJob(sharedFromThis(), this);
job->startRequest(verb, url, req, data);
return job;
}
void Account::setSslConfiguration(const QSslConfiguration &config)
{
_sslConfiguration = config;

View file

@ -44,6 +44,7 @@ class Account;
typedef QSharedPointer<Account> AccountPtr;
class QuotaInfo;
class AccessManager;
class SimpleNetworkJob;
/**
@ -114,9 +115,22 @@ public:
AbstractCredentials *credentials() const;
void setCredentials(AbstractCredentials *cred);
/** Create a network request on the account's QNAM.
*
* Network requests in AbstractNetworkJobs are created through
* this function. Other places should prefer to use jobs or
* sendRequest().
*/
QNetworkReply *sendRawRequest(const QByteArray &verb,
const QUrl &url,
QNetworkRequest req = QNetworkRequest(),
QIODevice *data = 0);
// For creating various network requests
QNetworkReply *sendRequest(const QByteArray &verb,
/** Create and start network job for a simple one-off request.
*
* More complicated requests typically create their own job types.
*/
SimpleNetworkJob *sendRequest(const QByteArray &verb,
const QUrl &url,
QNetworkRequest req = QNetworkRequest(),
QIODevice *data = 0);

View file

@ -303,10 +303,8 @@ bool HttpCredentials::refreshAccessToken()
requestToken.setPassword(Theme::instance()->oauthClientSecret());
QNetworkRequest req;
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
auto reply = _account->sendRequest("POST", requestToken, req);
QTimer::singleShot(30 * 1000, reply, &QNetworkReply::abort);
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply] {
reply->deleteLater();
auto job = _account->sendRequest("POST", requestToken, req);
QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) {
auto jsonData = reply->readAll();
QJsonParseError jsonParseError;
QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();

View file

@ -886,4 +886,23 @@ void DetermineAuthTypeJob::send(const QUrl &url)
sendRequest("GET", url, req);
}
SimpleNetworkJob::SimpleNetworkJob(AccountPtr account, QObject *parent)
: AbstractNetworkJob(account, QString(), parent)
{
}
QNetworkReply *SimpleNetworkJob::startRequest(const QByteArray &verb, const QUrl &url,
QNetworkRequest req, QIODevice *requestBody)
{
auto reply = sendRequest(verb, url, req, requestBody);
start();
return reply;
}
bool SimpleNetworkJob::finished()
{
emit finishedSignal(reply());
return true;
}
} // namespace OCC

View file

@ -377,6 +377,28 @@ private:
int _redirects;
};
/**
* @brief A basic job around a network request without extra funtionality
* @ingroup libsync
*
* Primarily adds timeout and redirection handling.
*/
class OWNCLOUDSYNC_EXPORT SimpleNetworkJob : public AbstractNetworkJob
{
Q_OBJECT
public:
explicit SimpleNetworkJob(AccountPtr account, QObject *parent = 0);
QNetworkReply *startRequest(const QByteArray &verb, const QUrl &url,
QNetworkRequest req = QNetworkRequest(),
QIODevice *requestBody = 0);
signals:
void finishedSignal(QNetworkReply *reply);
private slots:
bool finished() Q_DECL_OVERRIDE;
};
} // namespace OCC
#endif // NETWORKJOBS_H