force DomainServer to wait for session UUID before setup with auth

This commit is contained in:
Stephen Birarda 2014-02-19 18:06:21 -08:00
parent 32ceccfeb6
commit d3dd49a2e8
5 changed files with 104 additions and 30 deletions

View file

@ -43,20 +43,16 @@ DomainServer::DomainServer(int argc, char* argv[]) :
_hasCompletedRestartHold(false), _hasCompletedRestartHold(false),
_nodeAuthenticationURL(DEFAULT_NODE_AUTH_URL) _nodeAuthenticationURL(DEFAULT_NODE_AUTH_URL)
{ {
const char CUSTOM_PORT_OPTION[] = "-p"; _argumentList = arguments();
const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION);
unsigned short domainServerPort = customPortString ? atoi(customPortString) : DEFAULT_DOMAIN_SERVER_PORT;
QStringList argumentList = arguments();
int argumentIndex = 0; int argumentIndex = 0;
// check if this domain server should use no authentication or a custom hostname for authentication // 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"; const QString CUSTOM_AUTH_OPTION = "--customAuth";
if ((argumentIndex = argumentList.indexOf(NO_AUTH_OPTION) != -1)) { if ((argumentIndex = _argumentList.indexOf(NO_AUTH_OPTION) != -1)) {
_nodeAuthenticationURL = QUrl(); _nodeAuthenticationURL = QUrl();
} else if ((argumentIndex = argumentList.indexOf(CUSTOM_AUTH_OPTION)) != -1) { } else if ((argumentIndex = _argumentList.indexOf(CUSTOM_AUTH_OPTION)) != -1) {
_nodeAuthenticationURL = QUrl(argumentList.value(argumentIndex + 1)); _nodeAuthenticationURL = QUrl(_argumentList.value(argumentIndex + 1));
} }
if (!_nodeAuthenticationURL.isEmpty()) { if (!_nodeAuthenticationURL.isEmpty()) {
@ -72,7 +68,11 @@ DomainServer::DomainServer(int argc, char* argv[]) :
AccountManager& accountManager = AccountManager::getInstance(); AccountManager& accountManager = AccountManager::getInstance();
accountManager.setRootURL(_nodeAuthenticationURL); accountManager.setRootURL(_nodeAuthenticationURL);
// TODO: failure case for not receiving a token
accountManager.requestAccessToken(username, password); accountManager.requestAccessToken(username, password);
connect(&accountManager, &AccountManager::receivedAccessToken, this, &DomainServer::requestUUIDFromDataServer);
} else { } else {
qDebug() << "Authentication was requested against" << qPrintable(_nodeAuthenticationURL.toString()) qDebug() << "Authentication was requested against" << qPrintable(_nodeAuthenticationURL.toString())
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
@ -83,33 +83,66 @@ DomainServer::DomainServer(int argc, char* argv[]) :
return; 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<QNetworkReply*>(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<Assignment::Type> parsedTypes(QSet<Assignment::Type>() << Assignment::AgentType); QSet<Assignment::Type> parsedTypes(QSet<Assignment::Type>() << Assignment::AgentType);
parseCommandLineTypeConfigs(argumentList, parsedTypes); parseCommandLineTypeConfigs(_argumentList, parsedTypes);
const QString CONFIG_FILE_OPTION = "--configFile"; const QString CONFIG_FILE_OPTION = "--configFile";
if ((argumentIndex = argumentList.indexOf(CONFIG_FILE_OPTION)) != -1) { if ((argumentIndex = _argumentList.indexOf(CONFIG_FILE_OPTION)) != -1) {
QString configFilePath = argumentList.value(argumentIndex + 1); QString configFilePath = _argumentList.value(argumentIndex + 1);
readConfigFile(configFilePath, parsedTypes); readConfigFile(configFilePath, parsedTypes);
} }
populateDefaultStaticAssignmentsExcludingTypes(parsedTypes); populateDefaultStaticAssignmentsExcludingTypes(parsedTypes);
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort); NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort);
// create a random UUID for this session for the domain-server // 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::nodeAdded, this, &DomainServer::nodeAdded);
connect(nodeList, &NodeList::nodeKilled, this, &DomainServer::nodeKilled); connect(nodeList, &NodeList::nodeKilled, this, &DomainServer::nodeKilled);
QTimer* silentNodeTimer = new QTimer(this); QTimer* silentNodeTimer = new QTimer(this);
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams())); connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams()));
// fire a single shot timer to add static assignments back into the queue after a restart // 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())); QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart()));
} }

View file

@ -37,6 +37,8 @@ public slots:
void nodeKilled(SharedNodePointer node); void nodeKilled(SharedNodePointer node);
private: private:
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
void parseCommandLineTypeConfigs(const QStringList& argumentList, QSet<Assignment::Type>& excludedTypes); void parseCommandLineTypeConfigs(const QStringList& argumentList, QSet<Assignment::Type>& excludedTypes);
void readConfigFile(const QString& path, QSet<Assignment::Type>& excludedTypes); void readConfigFile(const QString& path, QSet<Assignment::Type>& excludedTypes);
QString readServerAssignmentConfig(const QJsonObject& jsonObject, const QString& nodeName); QString readServerAssignmentConfig(const QJsonObject& jsonObject, const QString& nodeName);
@ -60,7 +62,12 @@ private:
bool _hasCompletedRestartHold; bool _hasCompletedRestartHold;
QUrl _nodeAuthenticationURL; QUrl _nodeAuthenticationURL;
QStringList _argumentList;
private slots: private slots:
void requestUUIDFromDataServer();
void parseUUIDFromDataServer();
void readAvailableDatagrams(); void readAvailableDatagrams();
void addStaticAssignmentsBackToQueueAfterRestart(); void addStaticAssignmentsBackToQueueAfterRestart();
}; };

View file

@ -52,8 +52,10 @@ AccountManager::AccountManager() :
} }
} }
void AccountManager::authenticatedGetRequest(const QString& path, const QObject *successReceiver, const char *successMethod, void AccountManager::authenticatedRequest(const QString& path, AuthenticatedRequestMethod::Method method,
const QObject* errorReceiver, const char* errorMethod) { const QObject *successReceiver, const char *successMethod,
const QByteArray& dataByteArray,
const QObject* errorReceiver, const char* errorMethod) {
if (_networkAccessManager && hasValidAccessToken()) { if (_networkAccessManager && hasValidAccessToken()) {
QNetworkRequest authenticatedRequest; QNetworkRequest authenticatedRequest;
@ -63,13 +65,29 @@ void AccountManager::authenticatedGetRequest(const QString& path, const QObject
authenticatedRequest.setUrl(requestURL); 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); QNetworkReply* networkReply = NULL;
connect(networkReply, SIGNAL(finished()), successReceiver, successMethod);
if (errorReceiver && errorMethod) { switch (method) {
connect(networkReply, SIGNAL(error()), errorReceiver, errorMethod); 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); OAuthAccessToken freshAccessToken(rootObject);
_accessTokens.insert(rootURL, freshAccessToken); _accessTokens.insert(rootURL, freshAccessToken);
emit receivedAccessToken(rootURL);
// store this access token into the local settings // store this access token into the local settings
QSettings localSettings; QSettings localSettings;
localSettings.beginGroup(ACCOUNT_TOKEN_GROUP); localSettings.beginGroup(ACCOUNT_TOKEN_GROUP);

View file

@ -17,14 +17,26 @@
#include "OAuthAccessToken.h" #include "OAuthAccessToken.h"
namespace AuthenticatedRequestMethod {
enum Method {
GET,
POST,
PUT,
DELETE
};
}
class AccountManager : public QObject { class AccountManager : public QObject {
Q_OBJECT Q_OBJECT
public: public:
static AccountManager& getInstance(); static AccountManager& getInstance();
void authenticatedGetRequest(const QString& path, void authenticatedRequest(const QString& path,
const QObject* successReceiver, const char* successMethod, AuthenticatedRequestMethod::Method method,
const QObject* errorReceiver = 0, const char* errorMethod = NULL); 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; } void setRootURL(const QUrl& rootURL) { _rootURL = rootURL; }
@ -41,6 +53,7 @@ public slots:
void requestError(QNetworkReply::NetworkError error); void requestError(QNetworkReply::NetworkError error);
signals: signals:
void authenticationRequired(); void authenticationRequired();
void receivedAccessToken(const QUrl& rootURL);
private: private:
AccountManager(); AccountManager();
AccountManager(AccountManager const& other); // not implemented AccountManager(AccountManager const& other); // not implemented

View file

@ -586,9 +586,10 @@ void NodeList::domainServerAuthReply() {
} }
void NodeList::requestAuthForDomainServer() { void NodeList::requestAuthForDomainServer() {
AccountManager::getInstance().authenticatedGetRequest("/api/v1/domains/" AccountManager::getInstance().authenticatedRequest("/api/v1/domains/"
+ uuidStringWithoutCurlyBraces(_domainInfo.getUUID()) + "/auth.json", + uuidStringWithoutCurlyBraces(_domainInfo.getUUID()) + "/auth.json",
this, SLOT(domainServerAuthReply())); AuthenticatedRequestMethod::GET,
this, SLOT(domainServerAuthReply()));
} }
void NodeList::processDomainServerAuthRequest(const QByteArray& packet) { void NodeList::processDomainServerAuthRequest(const QByteArray& packet) {