From d3dd49a2e8ecc2d24cec1cffb7a938591d836dd6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 19 Feb 2014 18:06:21 -0800 Subject: [PATCH] force DomainServer to wait for session UUID before setup with auth --- domain-server/src/DomainServer.cpp | 67 ++++++++++++++++++------- domain-server/src/DomainServer.h | 7 +++ libraries/shared/src/AccountManager.cpp | 34 ++++++++++--- libraries/shared/src/AccountManager.h | 19 +++++-- libraries/shared/src/NodeList.cpp | 7 +-- 5 files changed, 104 insertions(+), 30 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index bff96aa57d..5321ee514f 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -43,20 +43,16 @@ DomainServer::DomainServer(int argc, char* argv[]) : _hasCompletedRestartHold(false), _nodeAuthenticationURL(DEFAULT_NODE_AUTH_URL) { - const char CUSTOM_PORT_OPTION[] = "-p"; - const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION); - unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT; - - QStringList argumentList = arguments(); + _argumentList = arguments(); int argumentIndex = 0; // check if this domain server should use no authentication or a custom hostname for authentication - const QString NO_AUTH_OPTION = "--hifiAuth"; + const QString NO_AUTH_OPTION = "--noAuth"; const QString CUSTOM_AUTH_OPTION = "--customAuth"; - if ((argumentIndex = argumentList.indexOf(NO_AUTH_OPTION) != -1)) { + if ((argumentIndex = _argumentList.indexOf(NO_AUTH_OPTION) != -1)) { _nodeAuthenticationURL = QUrl(); - } else if ((argumentIndex = argumentList.indexOf(CUSTOM_AUTH_OPTION)) != -1) { - _nodeAuthenticationURL = QUrl(argumentList.value(argumentIndex + 1)); + } else if ((argumentIndex = _argumentList.indexOf(CUSTOM_AUTH_OPTION)) != -1) { + _nodeAuthenticationURL = QUrl(_argumentList.value(argumentIndex + 1)); } if (!_nodeAuthenticationURL.isEmpty()) { @@ -72,7 +68,11 @@ DomainServer::DomainServer(int argc, char* argv[]) : AccountManager& accountManager = AccountManager::getInstance(); accountManager.setRootURL(_nodeAuthenticationURL); + // TODO: failure case for not receiving a token accountManager.requestAccessToken(username, password); + + connect(&accountManager, &AccountManager::receivedAccessToken, this, &DomainServer::requestUUIDFromDataServer); + } else { qDebug() << "Authentication was requested against" << qPrintable(_nodeAuthenticationURL.toString()) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) @@ -83,33 +83,66 @@ DomainServer::DomainServer(int argc, char* argv[]) : return; } + } else { + // auth is not requested for domain-server, setup NodeList and assignments now + setupNodeListAndAssignments(); + } +} + +void DomainServer::requestUUIDFromDataServer() { + // this slot is fired when we get a valid access token from the data-server + // now let's ask it to set us up with a UUID + AccountManager::getInstance().authenticatedRequest("/api/v1/domains/create", AuthenticatedRequestMethod::POST, + this, SLOT(parseUUIDFromDataServer())); +} + +void DomainServer::parseUUIDFromDataServer() { + QNetworkReply* requestReply = reinterpret_cast(sender()); + QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll()); + + if (jsonResponse.object()["status"].toString() == "success") { + // pull out the UUID the data-server is telling us to use, and complete our setup with it + QUuid newSessionUUID = QUuid(jsonResponse.object()["data"].toObject()["uuid"].toString()); + setupNodeListAndAssignments(newSessionUUID); + } +} + +void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { + + int argumentIndex = 0; + + const QString CUSTOM_PORT_OPTION = "-p"; + unsigned short domainServerPort = DEFAULT_DOMAIN_SERVER_PORT; + + if ((argumentIndex = _argumentList.indexOf(CUSTOM_PORT_OPTION)) != -1) { + domainServerPort = _argumentList.value(argumentIndex + 1).toUShort(); } QSet parsedTypes(QSet() << Assignment::AgentType); - parseCommandLineTypeConfigs(argumentList, parsedTypes); + parseCommandLineTypeConfigs(_argumentList, parsedTypes); const QString CONFIG_FILE_OPTION = "--configFile"; - if ((argumentIndex = argumentList.indexOf(CONFIG_FILE_OPTION)) != -1) { - QString configFilePath = argumentList.value(argumentIndex + 1); + if ((argumentIndex = _argumentList.indexOf(CONFIG_FILE_OPTION)) != -1) { + QString configFilePath = _argumentList.value(argumentIndex + 1); readConfigFile(configFilePath, parsedTypes); } populateDefaultStaticAssignmentsExcludingTypes(parsedTypes); - + NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort); // create a random UUID for this session for the domain-server - nodeList->setSessionUUID(QUuid::createUuid()); + nodeList->setSessionUUID(sessionUUID); connect(nodeList, &NodeList::nodeAdded, this, &DomainServer::nodeAdded); connect(nodeList, &NodeList::nodeKilled, this, &DomainServer::nodeKilled); - + QTimer* silentNodeTimer = new QTimer(this); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); - + connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams())); - + // fire a single shot timer to add static assignments back into the queue after a restart QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart())); } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index e6cf4ba6e6..51023b6fb4 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -37,6 +37,8 @@ public slots: void nodeKilled(SharedNodePointer node); private: + void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid()); + void parseCommandLineTypeConfigs(const QStringList& argumentList, QSet& excludedTypes); void readConfigFile(const QString& path, QSet& excludedTypes); QString readServerAssignmentConfig(const QJsonObject& jsonObject, const QString& nodeName); @@ -60,7 +62,12 @@ private: bool _hasCompletedRestartHold; QUrl _nodeAuthenticationURL; + + QStringList _argumentList; private slots: + void requestUUIDFromDataServer(); + void parseUUIDFromDataServer(); + void readAvailableDatagrams(); void addStaticAssignmentsBackToQueueAfterRestart(); }; diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index a2619c29c8..9a9a40bc0f 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -52,8 +52,10 @@ AccountManager::AccountManager() : } } -void AccountManager::authenticatedGetRequest(const QString& path, const QObject *successReceiver, const char *successMethod, - const QObject* errorReceiver, const char* errorMethod) { +void AccountManager::authenticatedRequest(const QString& path, AuthenticatedRequestMethod::Method method, + const QObject *successReceiver, const char *successMethod, + const QByteArray& dataByteArray, + const QObject* errorReceiver, const char* errorMethod) { if (_networkAccessManager && hasValidAccessToken()) { QNetworkRequest authenticatedRequest; @@ -63,13 +65,29 @@ void AccountManager::authenticatedGetRequest(const QString& path, const QObject authenticatedRequest.setUrl(requestURL); - qDebug() << "Making an authenticated GET request to" << requestURL; + qDebug() << "Making an authenticated request to" << qPrintable(requestURL.toString()); - QNetworkReply* networkReply = _networkAccessManager->get(authenticatedRequest); - connect(networkReply, SIGNAL(finished()), successReceiver, successMethod); + QNetworkReply* networkReply = NULL; - if (errorReceiver && errorMethod) { - connect(networkReply, SIGNAL(error()), errorReceiver, errorMethod); + switch (method) { + case AuthenticatedRequestMethod::GET: + networkReply = _networkAccessManager->get(authenticatedRequest); + break; + case AuthenticatedRequestMethod::POST: + authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray); + default: + // other methods not yet handled + break; + } + + if (networkReply) { + // if we ended up firing of a request, hook up to it now + connect(networkReply, SIGNAL(finished()), successReceiver, successMethod); + + if (errorReceiver && errorMethod) { + connect(networkReply, SIGNAL(error()), errorReceiver, errorMethod); + } } } } @@ -141,6 +159,8 @@ void AccountManager::requestFinished() { OAuthAccessToken freshAccessToken(rootObject); _accessTokens.insert(rootURL, freshAccessToken); + emit receivedAccessToken(rootURL); + // store this access token into the local settings QSettings localSettings; localSettings.beginGroup(ACCOUNT_TOKEN_GROUP); diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index 53608d94e2..6243162049 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -17,14 +17,26 @@ #include "OAuthAccessToken.h" +namespace AuthenticatedRequestMethod { + enum Method { + GET, + POST, + PUT, + DELETE + }; +} + class AccountManager : public QObject { Q_OBJECT public: + static AccountManager& getInstance(); - void authenticatedGetRequest(const QString& path, - const QObject* successReceiver, const char* successMethod, - const QObject* errorReceiver = 0, const char* errorMethod = NULL); + void authenticatedRequest(const QString& path, + AuthenticatedRequestMethod::Method method, + const QObject* successReceiver, const char* successMethod, + const QByteArray& dataByteArray = QByteArray(), + const QObject* errorReceiver = 0, const char* errorMethod = NULL); void setRootURL(const QUrl& rootURL) { _rootURL = rootURL; } @@ -41,6 +53,7 @@ public slots: void requestError(QNetworkReply::NetworkError error); signals: void authenticationRequired(); + void receivedAccessToken(const QUrl& rootURL); private: AccountManager(); AccountManager(AccountManager const& other); // not implemented diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 123b9541ab..ea4e63c863 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -586,9 +586,10 @@ void NodeList::domainServerAuthReply() { } void NodeList::requestAuthForDomainServer() { - AccountManager::getInstance().authenticatedGetRequest("/api/v1/domains/" - + uuidStringWithoutCurlyBraces(_domainInfo.getUUID()) + "/auth.json", - this, SLOT(domainServerAuthReply())); + AccountManager::getInstance().authenticatedRequest("/api/v1/domains/" + + uuidStringWithoutCurlyBraces(_domainInfo.getUUID()) + "/auth.json", + AuthenticatedRequestMethod::GET, + this, SLOT(domainServerAuthReply())); } void NodeList::processDomainServerAuthRequest(const QByteArray& packet) {