add auth to assignment-client, fix refresh of static assignments

This commit is contained in:
Stephen Birarda 2014-02-24 13:29:32 -08:00
parent fcb36f0aca
commit 27c779666b
8 changed files with 96 additions and 34 deletions

View file

@ -6,9 +6,11 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/QProcess>
#include <QtCore/QThread>
#include <QtCore/QTimer>
#include <AccountManager.h>
#include <Assignment.h>
#include <Logging.h>
#include <NodeList.h>
@ -91,6 +93,10 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// connect our readPendingDatagrams method to the readyRead() signal of the socket
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
// connections to AccountManager for authentication
connect(&AccountManager::getInstance(), &AccountManager::authRequired,
this, &AssignmentClient::handleAuthenticationRequest);
}
void AssignmentClient::sendAssignmentRequest() {
@ -158,6 +164,30 @@ void AssignmentClient::readPendingDatagrams() {
}
}
void AssignmentClient::handleAuthenticationRequest() {
const QString DATA_SERVER_USERNAME_ENV = "HIFI_AC_USERNAME";
const QString DATA_SERVER_PASSWORD_ENV = "HIFI_AC_PASSWORD";
// this node will be using an authentication server, let's make sure we have a username/password
QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment();
QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV);
QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV);
AccountManager& accountManager = AccountManager::getInstance();
if (!username.isEmpty() && !password.isEmpty()) {
// ask the account manager to log us in from the env variables
accountManager.requestAccessToken(username, password);
} else {
qDebug() << "Authentication was requested against" << qPrintable(accountManager.getRootURL().toString())
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
<< "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate.";
return;
}
}
void AssignmentClient::assignmentCompleted() {
// reset the logging target to the the CHILD_TARGET_NAME
Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
@ -175,5 +205,6 @@ void AssignmentClient::assignmentCompleted() {
// reset our NodeList by switching back to unassigned and clearing the list
nodeList->setOwnerType(NodeType::Unassigned);
nodeList->reset();
nodeList->getDomainInfo().reset();
nodeList->resetNodeInterestSet();
}

View file

@ -21,6 +21,7 @@ private slots:
void sendAssignmentRequest();
void readPendingDatagrams();
void assignmentCompleted();
void handleAuthenticationRequest();
private:
Assignment _requestAssignment;
ThreadedAssignment* _currentAssignment;

View file

@ -55,23 +55,24 @@ DomainServer::DomainServer(int argc, char* argv[]) :
}
if (!_nodeAuthenticationURL.isEmpty()) {
// this domain-server will be using an authentication server, let's make sure we have a username/password
QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment();
const QString DATA_SERVER_USERNAME_ENV = "HIFI_DS_USERNAME";
const QString DATA_SERVER_PASSWORD_ENV = "HIFI_DS_PASSWORD";
// this node will be using an authentication server, let's make sure we have a username/password
QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment();
QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV);
QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV);
AccountManager& accountManager = AccountManager::getInstance();
accountManager.setRootURL(_nodeAuthenticationURL);
if (!username.isEmpty() && !password.isEmpty()) {
AccountManager& accountManager = AccountManager::getInstance();
accountManager.setRootURL(_nodeAuthenticationURL);
// TODO: failure case for not receiving a token
accountManager.requestAccessToken(username, password);
connect(&accountManager, &AccountManager::loginComplete, this, &DomainServer::requestCreationFromDataServer);
// ask the account manager to log us in from the env variables
accountManager.requestAccessToken(username, password);
} else {
qDebug() << "Authentication was requested against" << qPrintable(_nodeAuthenticationURL.toString())
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
@ -82,6 +83,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
return;
}
} else {
// auth is not requested for domain-server, setup NodeList and assignments now
setupNodeListAndAssignments();
@ -326,27 +328,28 @@ void DomainServer::addNodeToNodeListAndConfirmConnection(const QByteArray& packe
int numPreInterestBytes = parseNodeDataFromByteArray(nodeType, publicSockAddr, localSockAddr, packet, senderSockAddr);
QUuid nodeUUID = uuidFromPacketHeader(packet);
QUuid assignmentUUID = uuidFromPacketHeader(packet);
SharedAssignmentPointer matchingAssignment;
if (!nodeUUID.isNull() && (matchingAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType))) {
if (!assignmentUUID.isNull() && (matchingAssignment = matchingStaticAssignmentForCheckIn(assignmentUUID, nodeType))
&& matchingAssignment) {
// this is an assigned node, make sure the UUID sent is for an assignment we're actually trying to give out
nodeUUID = uuidFromPacketHeader(packet);
if (matchingAssignment) {
// this was a newly added node with a matching assignment
// remove the matching assignment from the assignment queue so we don't take the next check in
// (if it exists)
removeMatchingAssignmentFromQueue(matchingAssignment);
}
// remove the matching assignment from the assignment queue so we don't take the next check in
// (if it exists)
removeMatchingAssignmentFromQueue(matchingAssignment);
} else {
assignmentUUID = QUuid();
}
// create a new session UUID for this node
nodeUUID = QUuid::createUuid();
QUuid nodeUUID = QUuid::createUuid();
SharedNodePointer newNode = NodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType, publicSockAddr, localSockAddr);
// when the newNode is created the linked data is also created, if this was a static assignment set the UUID
reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData())->setStaticAssignmentUUID(assignmentUUID);
if (!authJsonObject.isEmpty()) {
// pull the connection secret from the authJsonObject and set it as the connection secret for this node
QUuid connectionSecret(authJsonObject["data"].toObject()["connection_secret"].toString());
@ -779,19 +782,24 @@ void DomainServer::nodeAdded(SharedNodePointer node) {
}
void DomainServer::nodeKilled(SharedNodePointer node) {
// if this node's UUID matches a static assignment we need to throw it back in the assignment queue
SharedAssignmentPointer matchedAssignment = _staticAssignmentHash.value(node->getUUID());
if (matchedAssignment) {
refreshStaticAssignmentAndAddToQueue(matchedAssignment);
}
// cleanup the connection secrets that we set up for this node (on the other nodes)
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) {
SharedNodePointer otherNode = NodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID);
if (otherNode) {
reinterpret_cast<DomainServerNodeData*>(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID());
if (nodeData) {
// if this node's UUID matches a static assignment we need to throw it back in the assignment queue
if (!nodeData->getStaticAssignmentUUID().isNull()) {
SharedAssignmentPointer matchedAssignment = _staticAssignmentHash.value(nodeData->getStaticAssignmentUUID());
if (matchedAssignment) {
refreshStaticAssignmentAndAddToQueue(matchedAssignment);
}
}
// cleanup the connection secrets that we set up for this node (on the other nodes)
foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) {
SharedNodePointer otherNode = NodeList::getInstance()->nodeWithUUID(otherNodeSessionUUID);
if (otherNode) {
reinterpret_cast<DomainServerNodeData*>(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID());
}
}
}
}

View file

@ -0,0 +1,16 @@
//
// DomainServerNodeData.cpp
// hifi
//
// Created by Stephen Birarda on 2/6/2014.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include "DomainServerNodeData.h"
DomainServerNodeData::DomainServerNodeData() :
_sessionSecretHash(),
_staticAssignmentUUID()
{
}

View file

@ -10,17 +10,22 @@
#define __hifi__DomainServerNodeData__
#include <QtCore/QHash>
#include <QtCore/QUuid>
#include <NodeData.h>
class DomainServerNodeData : public NodeData {
public:
DomainServerNodeData() : _sessionSecretHash() {};
DomainServerNodeData();
int parseData(const QByteArray& packet) { return 0; }
void setStaticAssignmentUUID(const QUuid& staticAssignmentUUID) { _staticAssignmentUUID = staticAssignmentUUID; }
const QUuid& getStaticAssignmentUUID() const { return _staticAssignmentUUID; }
QHash<QUuid, QUuid>& getSessionSecretHash() { return _sessionSecretHash; }
private:
QHash<QUuid, QUuid> _sessionSecretHash;
QUuid _staticAssignmentUUID;
};
#endif /* defined(__hifi__DomainServerNodeData__) */

View file

@ -41,6 +41,7 @@ public:
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
const QByteArray& dataByteArray = QByteArray());
const QUrl& getRootURL() const { return _rootURL; }
void setRootURL(const QUrl& rootURL);
bool hasAuthEndpoint() { return !_rootURL.isEmpty(); }

View file

@ -31,7 +31,7 @@ void DomainInfo::reset() {
_hostname = QString();
_sockAddr.setAddress(QHostAddress::Null);
_assignmentUUID = QUuid();
_connectionSecret = QString();
_connectionSecret = QUuid();
_registrationToken = QByteArray();
_rootAuthenticationURL = QUrl();
_publicKey = QString();

View file

@ -24,6 +24,8 @@ class DomainInfo : public QObject {
public:
DomainInfo();
void reset();
void parseAuthInformationFromJsonObject(const QJsonObject& jsonObject);
const QUuid& getUUID() const { return _uuid; }
@ -62,8 +64,6 @@ signals:
void hostnameChanged(const QString& hostname);
void connectedToDomain(const QString& hostname);
private:
void reset();
QUuid _uuid;
QString _hostname;
HifiSockAddr _sockAddr;