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),
_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<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);
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()));
}

View file

@ -37,6 +37,8 @@ public slots:
void nodeKilled(SharedNodePointer node);
private:
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
void parseCommandLineTypeConfigs(const QStringList& argumentList, QSet<Assignment::Type>& excludedTypes);
void readConfigFile(const QString& path, QSet<Assignment::Type>& 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();
};

View file

@ -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);

View file

@ -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

View file

@ -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) {