hook up request for domain registration information for Interface

This commit is contained in:
Stephen Birarda 2014-02-18 15:38:40 -08:00
parent f4b0375b35
commit 949f79e945
10 changed files with 108 additions and 37 deletions

View file

@ -70,6 +70,9 @@ DomainServer::DomainServer(int argc, char* argv[]) :
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort);
// create a random UUID for this session for the domain-server
nodeList->setSessionUUID(QUuid::createUuid());
connect(nodeList, &NodeList::nodeAdded, this, &DomainServer::nodeAdded);
connect(nodeList, &NodeList::nodeKilled, this, &DomainServer::nodeKilled);

View file

@ -207,8 +207,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer)));
connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle);
connect(&AccountManager::getInstance(), SIGNAL(authenticationRequiredForRootURL(const QUrl&)),
Menu::getInstance(), SLOT(showLoginForRootURL(const QUrl&)));
connect(&AccountManager::getInstance(), SIGNAL(authenticationRequired()),
Menu::getInstance(), SLOT(loginForCurrentDomain()));
// read the ApplicationInfo.ini file for Name/Version/Domain information
QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat);

View file

@ -739,10 +739,6 @@ const int QLINE_MINIMUM_WIDTH = 400;
const float DIALOG_RATIO_OF_WINDOW = 0.30f;
void Menu::loginForCurrentDomain() {
showLoginForRootURL(NodeList::getInstance()->getDomainInfo().getRootAuthenticationURL());
}
void Menu::showLoginForRootURL(const QUrl& rootURL) {
QDialog loginDialog(Application::getInstance()->getWindow());
loginDialog.setWindowTitle("Login");
@ -765,14 +761,14 @@ void Menu::showLoginForRootURL(const QUrl& rootURL) {
loginDialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
loginDialog.connect(buttons, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(buttons);
int dialogReturn = loginDialog.exec();
if (dialogReturn == QDialog::Accepted && !usernameLineEdit->text().isEmpty() && !passwordLineEdit->text().isEmpty()) {
// attempt to get an access token given this username and password
AccountManager::getInstance().requestAccessToken(rootURL, usernameLineEdit->text(), passwordLineEdit->text());
AccountManager::getInstance().requestAccessToken(usernameLineEdit->text(), passwordLineEdit->text());
}
sendFakeEnterEvent();
}

View file

@ -102,7 +102,6 @@ public:
public slots:
void loginForCurrentDomain();
void showLoginForRootURL(const QUrl& rootURL);
void bandwidthDetails();
void voxelStatsDetails();
void lodTools();

View file

@ -18,6 +18,9 @@
#include "AccountManager.h"
QMap<QUrl, OAuthAccessToken> AccountManager::_accessTokens = QMap<QUrl, OAuthAccessToken>();
QMap<QUrl, QString> AccountManager::_clientIDs = QMap<QUrl, QString>();
AccountManager& AccountManager::getInstance() {
static AccountManager sharedInstance;
return sharedInstance;
@ -26,42 +29,67 @@ AccountManager& AccountManager::getInstance() {
const QString DEFAULT_NODE_AUTH_OAUTH_CLIENT_ID = "12b7b18e7b8c118707b84ff0735e57a4473b5b0577c2af44734f02e08d02829c";
AccountManager::AccountManager() :
_rootURL(),
_username(),
_accessTokens(),
_clientIDs(),
_networkAccessManager(NULL)
{
_clientIDs.insert(DEFAULT_NODE_AUTH_URL, DEFAULT_NODE_AUTH_OAUTH_CLIENT_ID);
}
bool AccountManager::hasValidAccessTokenForRootURL(const QUrl &rootURL) {
OAuthAccessToken accessToken = _accessTokens.value(rootURL);
void AccountManager::authenticatedGetRequest(const QString& path, const QObject *successReceiver, const char *successMethod,
const QObject* errorReceiver, const char* errorMethod) {
if (_networkAccessManager && hasValidAccessToken()) {
QNetworkRequest authenticatedRequest;
QUrl requestURL = _rootURL;
requestURL.setPath(path);
requestURL.setQuery("access_token=" + _accessTokens.value(_rootURL).token);
authenticatedRequest.setUrl(requestURL);
qDebug() << "Making an authenticated GET request to" << requestURL;
QNetworkReply* networkReply = _networkAccessManager->get(authenticatedRequest);
connect(networkReply, SIGNAL(finished()), successReceiver, successMethod);
if (errorReceiver && errorMethod) {
connect(networkReply, SIGNAL(error()), errorReceiver, errorMethod);
}
}
}
bool AccountManager::hasValidAccessToken() {
OAuthAccessToken accessToken = _accessTokens.value(_rootURL);
if (accessToken.token.isEmpty() || accessToken.isExpired()) {
qDebug() << "An access token is required for requests to" << qPrintable(rootURL.toString());
qDebug() << "An access token is required for requests to" << qPrintable(_rootURL.toString());
return false;
} else {
return true;
}
}
bool AccountManager::checkAndSignalForAccessTokenForRootURL(const QUrl& rootURL) {
if (!hasValidAccessTokenForRootURL(rootURL)) {
bool AccountManager::checkAndSignalForAccessToken() {
bool hasToken = hasValidAccessToken();
if (!hasToken) {
// emit a signal so somebody can call back to us and request an access token given a username and password
emit authenticationRequiredForRootURL(rootURL);
emit authenticationRequired();
}
return hasToken;
}
void AccountManager::requestAccessToken(const QUrl& rootURL, const QString& username, const QString& password) {
void AccountManager::requestAccessToken(const QString& username, const QString& password) {
if (_networkAccessManager) {
if (_clientIDs.contains(rootURL)) {
if (_clientIDs.contains(_rootURL)) {
QNetworkRequest request;
QUrl grantURL = rootURL;
QUrl grantURL = _rootURL;
grantURL.setPath("/oauth/token");
QByteArray postData;
postData.append("client_id=" + _clientIDs.value(rootURL) + "&");
postData.append("client_id=" + _clientIDs.value(_rootURL) + "&");
postData.append("grant_type=password&");
postData.append("username=" + username + "&");
postData.append("password=" + password);
@ -73,7 +101,7 @@ void AccountManager::requestAccessToken(const QUrl& rootURL, const QString& user
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestFinished);
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
} else {
qDebug() << "Client ID for OAuth authorization at" << rootURL.toString() << "is unknown. Cannot authenticate.";
qDebug() << "Client ID for OAuth authorization at" << _rootURL.toString() << "is unknown. Cannot authenticate.";
}
}
}
@ -96,7 +124,9 @@ void AccountManager::requestFinished() {
QUrl rootURL = requestReply->url();
rootURL.setPath("");
_accessTokens.insert(requestReply->url(), OAuthAccessToken(rootObject));
qDebug() << "Storing an access token for" << rootURL;
_accessTokens.insert(rootURL, OAuthAccessToken(rootObject));
}
} else {
// TODO: error handling
@ -105,5 +135,6 @@ void AccountManager::requestFinished() {
}
void AccountManager::requestError(QNetworkReply::NetworkError error) {
// TODO: error handling
qDebug() << "AccountManager requestError - " << error;
}

View file

@ -22,10 +22,16 @@ class AccountManager : public QObject {
public:
static AccountManager& getInstance();
bool hasValidAccessTokenForRootURL(const QUrl& rootURL);
bool checkAndSignalForAccessTokenForRootURL(const QUrl& rootURL);
void authenticatedGetRequest(const QString& path,
const QObject* successReceiver, const char* successMethod,
const QObject* errorReceiver = 0, const char* errorMethod = NULL);
void requestAccessToken(const QUrl& rootURL, const QString& username, const QString& password);
void setRootURL(const QUrl& rootURL) { _rootURL = rootURL; }
bool hasValidAccessToken();
bool checkAndSignalForAccessToken();
void requestAccessToken(const QString& username, const QString& password);
const QString& getUsername() const { return _username; }
void setUsername(const QString& username) { _username = username; }
@ -35,16 +41,18 @@ public slots:
void requestFinished();
void requestError(QNetworkReply::NetworkError error);
signals:
void authenticationRequiredForRootURL(const QUrl& rootURL);
void authenticationRequired();
private:
AccountManager();
AccountManager(AccountManager const& other); // not implemented
void operator=(AccountManager const& other); // not implemented
QUrl _rootURL;
QString _username;
QMap<QUrl, OAuthAccessToken> _accessTokens;
QMap<QUrl, QString> _clientIDs;
QNetworkAccessManager* _networkAccessManager;
static QMap<QUrl, OAuthAccessToken> _accessTokens;
static QMap<QUrl, QString> _clientIDs;
};
#endif /* defined(__hifi__AccountManager__) */

View file

@ -6,23 +6,35 @@
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/QJsonObject>
#include "DomainInfo.h"
DomainInfo::DomainInfo() :
_uuid(),
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
_connectionSecret(),
_registrationToken(),
_rootAuthenticationURL()
_rootAuthenticationURL(),
_publicKey()
{
}
void DomainInfo::reset() {
_uuid = QUuid();
_hostname = QString();
_sockAddr.setAddress(QHostAddress::Null);
_connectionSecret = QString();
_registrationToken = QString();
_rootAuthenticationURL = QUrl();
_publicKey = QString();
}
void DomainInfo::parseAuthInformationFromJsonObject(const QJsonObject& jsonObject) {
_connectionSecret = QUuid(jsonObject["connection_uuid"].toString());
_registrationToken = jsonObject["registration_token"].toString();
_publicKey = jsonObject["public_key"].toString();
}
void DomainInfo::setHostname(const QString& hostname) {

View file

@ -24,6 +24,11 @@ class DomainInfo : public QObject {
public:
DomainInfo();
void parseAuthInformationFromJsonObject(const QJsonObject& jsonObject);
const QUuid& getUUID() const { return _uuid; }
void setUUID(const QUuid& uuid) { _uuid = uuid; }
const QString& getHostname() const { return _hostname; }
void setHostname(const QString& hostname);
@ -51,11 +56,13 @@ signals:
private:
void reset();
QUuid _uuid;
QString _hostname;
HifiSockAddr _sockAddr;
QUuid _connectionSecret;
QString _registrationToken;
QUrl _rootAuthenticationURL;
QString _publicKey;
};
#endif /* defined(__hifi__DomainInfo__) */

View file

@ -12,6 +12,7 @@
#include <QtCore/QDataStream>
#include <QtCore/QDebug>
#include <QtCore/QJsonDocument>
#include <QtCore/QUrl>
#include <QtNetwork/QHostInfo>
@ -508,7 +509,7 @@ void NodeList::sendDomainServerCheckIn() {
// increment the count of un-replied check-ins
_numNoReplyDomainCheckIns++;
} else if (!_domainInfo.getRootAuthenticationURL().isEmpty() && _sessionUUID.isNull()
&& AccountManager::getInstance().hasValidAccessTokenForRootURL(_domainInfo.getRootAuthenticationURL())) {
&& AccountManager::getInstance().hasValidAccessToken()) {
// we have an access token we can use for the authentication server the domain-server requested
// so ask that server to provide us with information to connect to the domain-server
requestAuthForDomainServer();
@ -571,21 +572,34 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
return readNodes;
}
void NodeList::requestAuthForDomainServer() {
void NodeList::domainServerAuthReply() {
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
_domainInfo.parseAuthInformationFromJsonObject(jsonResponse.object());
}
void NodeList::requestAuthForDomainServer() {
AccountManager::getInstance().authenticatedGetRequest("/api/v1/domains/"
+ uuidStringWithoutCurlyBraces(_domainInfo.getUUID()) + "/auth.json",
this, SLOT(domainServerAuthReply()));
}
void NodeList::processDomainServerAuthRequest(const QByteArray& packet) {
QDataStream authPacketStream(packet);
authPacketStream.skipRawData(numBytesForPacketHeader(packet));
_domainInfo.setUUID(uuidFromPacketHeader(packet));
AccountManager& accountManager = AccountManager::getInstance();
// grab the hostname this domain-server wants us to authenticate with
QUrl authenticationRootURL;
authPacketStream >> authenticationRootURL;
accountManager.setRootURL(authenticationRootURL);
_domainInfo.setRootAuthenticationURL(authenticationRootURL);
if (AccountManager::getInstance().checkAndSignalForAccessTokenForRootURL(authenticationRootURL)) {
if (AccountManager::getInstance().checkAndSignalForAccessToken()) {
// request a domain-server auth
requestAuthForDomainServer();
}

View file

@ -130,7 +130,8 @@ signals:
void uuidChanged(const QUuid& ownerUUID);
void nodeAdded(SharedNodePointer);
void nodeKilled(SharedNodePointer);
private slots:
void domainServerAuthReply();
private:
static NodeList* _sharedInstance;