From c9dc91900fb5c1eb8f1b10235560de8464be14cb Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 15 Dec 2016 16:31:44 -0800 Subject: [PATCH] Checkpoint --- domain-server/src/DomainServer.cpp | 1 + .../src/DomainServerSettingsManager.cpp | 51 +++++++++++++++++++ .../src/DomainServerSettingsManager.h | 1 + interface/resources/qml/hifi/Pal.qml | 5 ++ libraries/networking/src/NodeList.cpp | 37 ++++++++++++++ libraries/networking/src/NodeList.h | 3 ++ .../networking/src/udt/PacketHeaders.cpp | 4 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- .../src/UsersScriptingInterface.cpp | 6 +++ .../src/UsersScriptingInterface.h | 13 +++++ scripts/system/pal.js | 12 ++++- 11 files changed, 132 insertions(+), 4 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 3dd75a19b2..0f7923519b 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -532,6 +532,7 @@ void DomainServer::setupNodeListAndAssignments() { // NodeList won't be available to the settings manager when it is created, so call registerListener here packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket"); packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket"); + packetReceiver.registerListener(PacketType::UsernameFromIDRequest, &_settingsManager, "processUsernameFromIDRequestPacket"); // register the gatekeeper for the packets it needs to receive packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket"); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 18a46e0658..d586c6318f 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -748,6 +748,57 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer message, SharedNodePointer sendingNode) { + // before we do any processing on this packet make sure it comes from a node that is allowed to kick + if (sendingNode->getCanKick()) { + // pull the UUID being kicked from the packet + QUuid nodeUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + + if (!nodeUUID.isNull() && nodeUUID != sendingNode->getUUID()) { + // make sure we actually have a node with this UUID + auto limitedNodeList = DependencyManager::get(); + + auto matchingNode = limitedNodeList->nodeWithUUID(nodeUUID); + + if (matchingNode) { + // we have a matching node, time to decide how to store updated permissions for this node + + NodePermissionsPointer destinationPermissions; + + QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName(); + + bool newPermissions = false; + + if (!verifiedUsername.isEmpty()) { + QByteArray printableVerifiedUsername = qPrintable(verifiedUsername); + // setup the packet + auto usernameFromIDRequestPacket = NLPacket::create(PacketType::UsernameFromIDRequest, NUM_BYTES_RFC4122_UUID + printableVerifiedUsername.length(), true); + + // write the node ID to the packet + usernameFromIDRequestPacket->write(nodeUUID.toRfc4122()); + // write the username to the packet + usernameFromIDRequestPacket->write(printableVerifiedUsername); + + auto nodeList = DependencyManager::get(); + nodeList->sendPacket(std::move(usernameFromIDRequestPacket), message->getSenderSockAddr()); + } + } + else { + qWarning() << "Node username request received for unknown node. Refusing to process."; + } + } + else { + // this isn't a UUID we can use + qWarning() << "Node username request received for invalid node ID. Refusing to process."; + } + + } + else { + qWarning() << "Refusing to process a username request packet from node" << uuidStringWithoutCurlyBraces(sendingNode->getUUID()) + << "that does not have kick permissions."; + } +} + QStringList DomainServerSettingsManager::getAllNames() const { QStringList result; foreach (auto key, _agentPermissions.keys()) { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 06ad7decd1..8c6155b3c0 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -113,6 +113,7 @@ public slots: private slots: void processSettingsRequestPacket(QSharedPointer message); void processNodeKickRequestPacket(QSharedPointer message, SharedNodePointer sendingNode); + void processUsernameFromIDRequestPacket(QSharedPointer message, SharedNodePointer sendingNode); private: QStringList _argumentList; diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 382b8fc962..a96353d7f0 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -72,6 +72,11 @@ Rectangle { table.selection.deselect(userIndex); } break; + case 'updateUsername': + var userId = message.params[0]; + var userName = message.params[1]; + var userIndex = findSessionIndex(userId); + table.get(userIndex).itemCell.nameCard.userName = userName; default: console.log('Unrecognized message:', JSON.stringify(message)); } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 29b7ea0385..57c5063604 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -127,6 +127,7 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) packetReceiver.registerListener(PacketType::ICEPingReply, &_domainHandler, "processICEPingReplyPacket"); packetReceiver.registerListener(PacketType::DomainServerPathResponse, this, "processDomainServerPathResponse"); packetReceiver.registerListener(PacketType::DomainServerRemovedNode, this, "processDomainServerRemovedNode"); + packetReceiver.registerListener(PacketType::UsernameFromIDRequest, this, "processUsernameFromIDRequestPacket"); } qint64 NodeList::sendStats(QJsonObject statsObject, HifiSockAddr destination) { @@ -889,3 +890,39 @@ void NodeList::muteNodeBySessionID(const QUuid& nodeID) { } } + +void NodeList::requestUsernameFromSessionID(const QUuid& nodeID) { + // send a request to domain-server to get the username associated with the given session ID + + if (!nodeID.isNull()) { + if (getThisNodeCanKick()) { + // setup the packet + auto usernameFromIDRequestPacket = NLPacket::create(PacketType::UsernameFromIDRequest, NUM_BYTES_RFC4122_UUID, true); + + // write the node ID to the packet + usernameFromIDRequestPacket->write(nodeID.toRfc4122()); + + qDebug() << "Sending packet to get username of node" << uuidStringWithoutCurlyBraces(nodeID); + + sendPacket(std::move(usernameFromIDRequestPacket), _domainHandler.getSockAddr()); + } + else { + qWarning() << "You do not have permissions to kick in this domain." + << "Request to get the username of node" << uuidStringWithoutCurlyBraces(nodeID) << "will not be sent"; + } + } + else { + qWarning() << "NodeList::requestUsernameFromSessionID called with an invalid ID."; + + } +} + +void NodeList::processUsernameFromIDRequestPacket(QSharedPointer message) { + // read the UUID from the packet + // read the UUID from the packet, remove it if it exists + QUuid nodeUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + // read the username from the packet + QString username = message->readString(); + + emit usernameFromID(nodeUUID, username); +} diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 9a9b85b851..8f69f9dc7f 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -81,6 +81,8 @@ public: void kickNodeBySessionID(const QUuid& nodeID); void muteNodeBySessionID(const QUuid& nodeID); + void requestUsernameFromSessionID(const QUuid& nodeID); + void processUsernameFromIDRequestPacket(QSharedPointer message); public slots: void reset(); @@ -108,6 +110,7 @@ signals: void receivedDomainServerList(); void ignoredNode(const QUuid& nodeID); void ignoreRadiusEnabledChanged(bool isIgnored); + void usernameFromID(QUuid& nodeID, QString& username); private slots: void stopKeepalivePingTimer(); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 34a70f8da6..ec904f9ba8 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -26,8 +26,8 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketType::NodeJsonStats << PacketType::EntityQuery << PacketType::OctreeDataNack << PacketType::EntityEditNack << PacketType::DomainListRequest << PacketType::StopNode - << PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest - << PacketType::NodeMuteRequest; + << PacketType::DomainDisconnectRequest << PacketType::UsernameFromIDRequest + << PacketType::NodeKickRequest << PacketType::NodeMuteRequest; const QSet NON_SOURCED_PACKETS = QSet() << PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index dbeb1e63b0..513b0c3b8c 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -101,7 +101,8 @@ public: NodeKickRequest, NodeMuteRequest, RadiusIgnoreRequest, - LAST_PACKET_TYPE = RadiusIgnoreRequest + UsernameFromIDRequest, + LAST_PACKET_TYPE = UsernameFromIDRequest }; }; diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 83181f7509..d774733cea 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -18,6 +18,7 @@ UsersScriptingInterface::UsersScriptingInterface() { auto nodeList = DependencyManager::get(); connect(nodeList.data(), &LimitedNodeList::canKickChanged, this, &UsersScriptingInterface::canKickChanged); connect(nodeList.data(), &NodeList::ignoreRadiusEnabledChanged, this, &UsersScriptingInterface::ignoreRadiusEnabledChanged); + connect(nodeList.data(), &NodeList::usernameFromID, this, &UsersScriptingInterface::usernameFromID); } void UsersScriptingInterface::ignore(const QUuid& nodeID) { @@ -35,6 +36,11 @@ void UsersScriptingInterface::mute(const QUuid& nodeID) { DependencyManager::get()->muteNodeBySessionID(nodeID); } +void UsersScriptingInterface::requestUsernameFromID(const QUuid& nodeID) { + // ask the Domain Server via the NodeList for the username associated with the given session ID + DependencyManager::get()->requestUsernameFromSessionID(nodeID); +} + bool UsersScriptingInterface::getCanKick() { // ask the NodeList to return our ability to kick return DependencyManager::get()->getThisNodeCanKick(); diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 87e8c7e0d8..a1d41c5fac 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -51,6 +51,13 @@ public slots: */ void mute(const QUuid& nodeID); + /**jsdoc + * Returns a string containing the username associated with the given Avatar UUID + * @function Users.getUsernameFromID + * @param {nodeID} nodeID The node or session ID of the user whose username you want. + */ + void requestUsernameFromID(const QUuid& nodeID); + /**jsdoc * Returns `true` if the DomainServer will allow this Node/Avatar to make kick * @function Users.getCanKick @@ -92,6 +99,12 @@ signals: * @function Users.enteredIgnoreRadius */ void enteredIgnoreRadius(); + + /**jsdoc + * Notifies scripts of the username associated with a UUID. + * @function Users.enteredIgnoreRadius + */ + void usernameFromID(QUuid& nodeID, QString& username); }; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 175418cd2e..cdfc9bb15c 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -118,9 +118,12 @@ function populateUserList() { var avatar = AvatarList.getAvatar(id); var avatarPalDatum = { displayName: avatar.displayName || ('anonymous ' + counter++), - userName: "fakeAcct" + (id || "Me"), + userName: Users.canKick ? 'Obtaining username...' : '', sessionId: id || '' }; + if (Users.canKick) { + Users.getUsernameFromID(id); + } data.push(avatarPalDatum); if (id) { // No overlay for ourself. addAvatarNode(id); @@ -129,6 +132,13 @@ function populateUserList() { }); pal.sendToQml({method: 'users', params: data}); } + +function usernameFromID(id, username) { + var data = { id: id, username: username }; + print('Username Data:', JSON.stringify(data)); + pal.sendToQml({ method: 'updateUsername', params: data }); +} + var pingPong = true; function updateOverlays() { var eye = Camera.position;