fix cross-thread calls to AccountManager, domain switch flow

This commit is contained in:
Stephen Birarda 2014-02-21 13:45:39 -08:00
parent d56bafc9a5
commit 9d2d9c5071
3 changed files with 57 additions and 24 deletions

View file

@ -26,17 +26,21 @@ AccountManager& AccountManager::getInstance() {
} }
Q_DECLARE_METATYPE(OAuthAccessToken) Q_DECLARE_METATYPE(OAuthAccessToken)
Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
Q_DECLARE_METATYPE(JSONCallbackParameters)
const QString ACCOUNT_TOKEN_GROUP = "tokens"; const QString ACCOUNT_TOKEN_GROUP = "tokens";
AccountManager::AccountManager() : AccountManager::AccountManager() :
_rootURL(), _rootURL(),
_username(), _username(),
_networkAccessManager(new QNetworkAccessManager), _networkAccessManager(),
_pendingCallbackMap() _pendingCallbackMap()
{ {
qRegisterMetaType<OAuthAccessToken>("OAuthAccessToken"); qRegisterMetaType<OAuthAccessToken>("OAuthAccessToken");
qRegisterMetaTypeStreamOperators<OAuthAccessToken>("OAuthAccessToken"); qRegisterMetaTypeStreamOperators<OAuthAccessToken>("OAuthAccessToken");
qRegisterMetaType<QNetworkAccessManager::Operation>("QNetworkAccessManager::Operation");
qRegisterMetaType<JSONCallbackParameters>("JSONCallbackParameters");
// check if there are existing access tokens to load from settings // check if there are existing access tokens to load from settings
QSettings settings; QSettings settings;
@ -53,9 +57,32 @@ AccountManager::AccountManager() :
} }
} }
void AccountManager::setRootURL(const QUrl& rootURL) {
if (_rootURL != rootURL) {
_rootURL = rootURL;
// we have an auth URL change, set the username empty
// we will need to ask for profile information again
_username.clear();
qDebug() << "URL for node authentication has been changed to" << qPrintable(_rootURL.toString());
qDebug() << "Re-setting authentication flow.";
}
}
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation, void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) { const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) {
if (_networkAccessManager && hasValidAccessToken()) { QMetaObject::invokeMethod(this, "invokedRequest",
Q_ARG(const QString&, path),
Q_ARG(QNetworkAccessManager::Operation, operation),
Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(const QByteArray&, dataByteArray));
}
void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) {
if (hasValidAccessToken()) {
QNetworkRequest authenticatedRequest; QNetworkRequest authenticatedRequest;
QUrl requestURL = _rootURL; QUrl requestURL = _rootURL;
@ -70,11 +97,11 @@ void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessMan
switch (operation) { switch (operation) {
case QNetworkAccessManager::GetOperation: case QNetworkAccessManager::GetOperation:
networkReply = _networkAccessManager->get(authenticatedRequest); networkReply = _networkAccessManager.get(authenticatedRequest);
break; break;
case QNetworkAccessManager::PostOperation: case QNetworkAccessManager::PostOperation:
authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray); networkReply = _networkAccessManager.post(authenticatedRequest, dataByteArray);
default: default:
// other methods not yet handled // other methods not yet handled
break; break;
@ -155,24 +182,22 @@ bool AccountManager::checkAndSignalForAccessToken() {
} }
void AccountManager::requestAccessToken(const QString& login, const QString& password) { void AccountManager::requestAccessToken(const QString& login, const QString& password) {
if (_networkAccessManager) { QNetworkRequest request;
QNetworkRequest request;
QUrl grantURL = _rootURL;
QUrl grantURL = _rootURL; grantURL.setPath("/oauth/token");
grantURL.setPath("/oauth/token");
QByteArray postData;
QByteArray postData; postData.append("grant_type=password&");
postData.append("grant_type=password&"); postData.append("username=" + login + "&");
postData.append("username=" + login + "&"); postData.append("password=" + password);
postData.append("password=" + password);
request.setUrl(grantURL);
request.setUrl(grantURL); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* requestReply = _networkAccessManager.post(request, postData);
QNetworkReply* requestReply = _networkAccessManager->post(request, postData); connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestFinished);
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestFinished); connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
}
} }

View file

@ -42,7 +42,7 @@ public:
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(), const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
const QByteArray& dataByteArray = QByteArray()); const QByteArray& dataByteArray = QByteArray());
void setRootURL(const QUrl& rootURL) { _rootURL = rootURL; } void setRootURL(const QUrl& rootURL);
bool hasValidAccessToken(); bool hasValidAccessToken();
bool checkAndSignalForAccessToken(); bool checkAndSignalForAccessToken();
@ -66,9 +66,12 @@ private:
AccountManager(AccountManager const& other); // not implemented AccountManager(AccountManager const& other); // not implemented
void operator=(AccountManager const& other); // not implemented void operator=(AccountManager const& other); // not implemented
Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray);
QUrl _rootURL; QUrl _rootURL;
QString _username; QString _username;
QNetworkAccessManager* _networkAccessManager; QNetworkAccessManager _networkAccessManager;
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap; QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
static QMap<QUrl, OAuthAccessToken> _accessTokens; static QMap<QUrl, OAuthAccessToken> _accessTokens;

View file

@ -111,8 +111,13 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
if (checkType == PacketTypeDomainList) { if (checkType == PacketTypeDomainList) {
if (_domainInfo.getRootAuthenticationURL().isEmpty() && _domainInfo.getUUID().isNull()) { if (_domainInfo.getRootAuthenticationURL().isEmpty() && _domainInfo.getUUID().isNull()) {
// if this is a domain-server that doesn't require auth,
// pull the UUID from this packet and set it as our domain-server UUID // pull the UUID from this packet and set it as our domain-server UUID
_domainInfo.setUUID(uuidFromPacketHeader(packet)); _domainInfo.setUUID(uuidFromPacketHeader(packet));
// we also know this domain-server requires no authentication
// so set the account manager root URL empty
AccountManager::getInstance().setRootURL(QUrl());
} }
if (_domainInfo.getUUID() == uuidFromPacketHeader(packet)) { if (_domainInfo.getUUID() == uuidFromPacketHeader(packet)) {