Merge pull request #9226 from zfox23/Get_Username_From_UUID

Show Usernames to Admins in PAL
This commit is contained in:
Zach Fox 2016-12-19 11:48:31 -08:00 committed by GitHub
commit aeb40a6e0c
11 changed files with 151 additions and 7 deletions

View file

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

View file

@ -748,6 +748,45 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer<Re
}
}
// This function processes the "Get Username from ID" request.
void DomainServerSettingsManager::processUsernameFromIDRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
// Before we do any processing on this packet, make sure it comes from a node that is allowed to kick (is an admin)
if (sendingNode->getCanKick()) {
// From the packet, pull the UUID we're identifying
QUuid nodeUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
if (!nodeUUID.isNull()) {
// First, make sure we actually have a node with this UUID
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
auto matchingNode = limitedNodeList->nodeWithUUID(nodeUUID);
// If we do have a matching node...
if (matchingNode) {
// It's time to figure out the username
QString verifiedUsername = matchingNode->getPermissions().getVerifiedUserName();
// Setup the packet
auto usernameFromIDReplyPacket = NLPacket::create(PacketType::UsernameFromIDReply);
usernameFromIDReplyPacket->write(nodeUUID.toRfc4122());
usernameFromIDReplyPacket->writeString(verifiedUsername);
qDebug() << "Sending username" << verifiedUsername << "associated with node" << nodeUUID;
// Ship it!
limitedNodeList->sendPacket(std::move(usernameFromIDReplyPacket), *sendingNode);
} else {
qWarning() << "Node username request received for unknown node. Refusing to process.";
}
} else {
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()) {

View file

@ -113,6 +113,7 @@ public slots:
private slots:
void processSettingsRequestPacket(QSharedPointer<ReceivedMessage> message);
void processNodeKickRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void processUsernameFromIDRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
private:
QStringList _argumentList;

View file

@ -72,6 +72,24 @@ Rectangle {
table.selection.deselect(userIndex);
}
break;
// Received an "updateUsername()" request from the JS
case 'updateUsername':
// The User ID (UUID) is the first parameter in the message.
var userId = message.params[0];
// The text that goes in the userName field is the second parameter in the message.
var userName = message.params[1];
// If the userId is empty, we're updating "myData".
if (!userId) {
myData.userName = userName;
myCard.userName = userName; // Defensive programming
} else {
// Get the index in userModel and userData associated with the passed UUID
var userIndex = findSessionIndex(userId);
// Set the userName appropriately
userModel.get(userIndex).userName = userName;
userData[userIndex].userName = userName; // Defensive programming
}
break;
default:
console.log('Unrecognized message:', JSON.stringify(message));
}

View file

@ -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::UsernameFromIDReply, this, "processUsernameFromIDReply");
}
qint64 NodeList::sendStats(QJsonObject statsObject, HifiSockAddr destination) {
@ -889,3 +890,36 @@ 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 (getThisNodeCanKick() || nodeID.isNull()) {
// setup the packet
auto usernameFromIDRequestPacket = NLPacket::create(PacketType::UsernameFromIDRequest, NUM_BYTES_RFC4122_UUID, true);
// write the node ID to the packet
if (nodeID.isNull()) {
usernameFromIDRequestPacket->write(getSessionUUID().toRfc4122());
} else {
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";
}
}
void NodeList::processUsernameFromIDReply(QSharedPointer<ReceivedMessage> message) {
// read the UUID from the packet
QString nodeUUIDString = (QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID))).toString();
// read the username from the packet
QString username = message->readString();
qDebug() << "Got username" << username << "for node" << nodeUUIDString;
emit usernameFromIDReply(nodeUUIDString, username);
}

View file

@ -81,6 +81,7 @@ public:
void kickNodeBySessionID(const QUuid& nodeID);
void muteNodeBySessionID(const QUuid& nodeID);
void requestUsernameFromSessionID(const QUuid& nodeID);
public slots:
void reset();
@ -99,6 +100,8 @@ public slots:
void processICEPingPacket(QSharedPointer<ReceivedMessage> message);
void processUsernameFromIDReply(QSharedPointer<ReceivedMessage> message);
#if (PR_BUILD || DEV_BUILD)
void toggleSendNewerDSConnectVersion(bool shouldSendNewerVersion) { _shouldSendNewerVersion = shouldSendNewerVersion; }
#endif
@ -108,6 +111,7 @@ signals:
void receivedDomainServerList();
void ignoredNode(const QUuid& nodeID);
void ignoreRadiusEnabledChanged(bool isIgnored);
void usernameFromIDReply(const QString& nodeID, const QString& username);
private slots:
void stopKeepalivePingTimer();

View file

@ -26,8 +26,8 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
<< 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<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
<< PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment
@ -39,12 +39,12 @@ const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
<< PacketType::ICEServerPeerInformation << PacketType::ICEServerQuery << PacketType::ICEServerHeartbeat
<< PacketType::ICEServerHeartbeatACK << PacketType::ICEPing << PacketType::ICEPingReply
<< PacketType::ICEServerHeartbeatDenied << PacketType::AssignmentClientStatus << PacketType::StopNode
<< PacketType::DomainServerRemovedNode;
<< PacketType::DomainServerRemovedNode << PacketType::UsernameFromIDReply;
PacketVersion versionForPacketType(PacketType packetType) {
switch (packetType) {
case PacketType::DomainList:
return static_cast<PacketVersion>(DomainListVersion::PermissionsGrid);
return static_cast<PacketVersion>(DomainListVersion::GetUsernameFromUUIDSupport);
case PacketType::EntityAdd:
case PacketType::EntityEdit:
case PacketType::EntityData:

View file

@ -101,7 +101,9 @@ public:
NodeKickRequest,
NodeMuteRequest,
RadiusIgnoreRequest,
LAST_PACKET_TYPE = RadiusIgnoreRequest
UsernameFromIDRequest,
UsernameFromIDReply,
LAST_PACKET_TYPE = UsernameFromIDReply
};
};
@ -226,7 +228,8 @@ enum class DomainServerAddedNodeVersion : PacketVersion {
enum class DomainListVersion : PacketVersion {
PrePermissionsGrid = 18,
PermissionsGrid
PermissionsGrid,
GetUsernameFromUUIDSupport
};
enum class AudioVersion : PacketVersion {

View file

@ -18,6 +18,7 @@ UsersScriptingInterface::UsersScriptingInterface() {
auto nodeList = DependencyManager::get<NodeList>();
connect(nodeList.data(), &LimitedNodeList::canKickChanged, this, &UsersScriptingInterface::canKickChanged);
connect(nodeList.data(), &NodeList::ignoreRadiusEnabledChanged, this, &UsersScriptingInterface::ignoreRadiusEnabledChanged);
connect(nodeList.data(), &NodeList::usernameFromIDReply, this, &UsersScriptingInterface::usernameFromIDReply);
}
void UsersScriptingInterface::ignore(const QUuid& nodeID) {
@ -35,6 +36,11 @@ void UsersScriptingInterface::mute(const QUuid& nodeID) {
DependencyManager::get<NodeList>()->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<NodeList>()->requestUsernameFromSessionID(nodeID);
}
bool UsersScriptingInterface::getCanKick() {
// ask the NodeList to return our ability to kick
return DependencyManager::get<NodeList>()->getThisNodeCanKick();

View file

@ -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 usernameFromIDReply(const QString& nodeID, const QString& username);
};

View file

@ -118,9 +118,15 @@ function populateUserList() {
var avatar = AvatarList.getAvatar(id);
var avatarPalDatum = {
displayName: avatar.displayName || ('anonymous ' + counter++),
userName: "fakeAcct" + (id || "Me"),
userName: '',
sessionId: id || ''
};
// If the current user is an admin OR
// they're requesting their own username ("id" is blank)...
if (Users.canKick || !id) {
// Request the username from the given UUID
Users.requestUsernameFromID(id);
}
data.push(avatarPalDatum);
if (id) { // No overlay for ourself.
addAvatarNode(id);
@ -129,6 +135,23 @@ function populateUserList() {
});
pal.sendToQml({method: 'users', params: data});
}
// The function that handles the reply from the server
function usernameFromIDReply(id, username) {
var data;
// If the ID we've received is our ID...
if (AvatarList.getAvatar('').sessionUUID === id) {
// Set the data to contain specific strings.
data = ['', username + ' (hidden)']
} else {
// Set the data to contain the ID and the username+ID concat string.
data = [id, username + '/' + id];
}
print('Username Data:', JSON.stringify(data));
// Ship the data off to QML
pal.sendToQml({ method: 'updateUsername', params: data });
}
var pingPong = true;
function updateOverlays() {
var eye = Camera.position;
@ -249,6 +272,7 @@ function onVisibileChanged() {
button.clicked.connect(onClicked);
pal.visibleChanged.connect(onVisibileChanged);
pal.closed.connect(off);
Users.usernameFromIDReply.connect(usernameFromIDReply);
//
// Cleanup.
@ -258,6 +282,7 @@ Script.scriptEnding.connect(function () {
toolBar.removeButton(buttonName);
pal.visibleChanged.disconnect(onVisibileChanged);
pal.closed.disconnect(off);
Users.usernameFromIDReply.disconnect(usernameFromIDReply);
off();
});