From 78cc98bc7b3d6549a47f08f975e518b74c6b35d8 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Thu, 11 Mar 2021 01:03:54 -0500 Subject: [PATCH 01/12] Add improved functionality for `Users.kick` API. Add banByUsername, banByFingerprint, and banByIP parameters. --- .../src/DomainServerSettingsManager.cpp | 103 ++++++++++++------ interface/src/Application.cpp | 6 +- interface/src/Application.h | 2 +- libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 2 +- .../src/UsersScriptingInterface.cpp | 7 +- .../src/UsersScriptingInterface.h | 12 +- 7 files changed, 90 insertions(+), 50 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 08cf56b188..8d1a479407 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -863,6 +863,18 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointerreadWithoutCopy(NUM_BYTES_RFC4122_UUID)); + bool hasOptionalBanParameters = false; + bool banByUsername = false; + bool banByFingerprint = false; + bool banByIP = false; + // pull optional ban parameters from the packet + if (message.data()->getSize() > NUM_BYTES_RFC4122_UUID) { + hasOptionalBanParameters = true; + message->readPrimitive(&banByUsername); + message->readPrimitive(&banByFingerprint); + message->readPrimitive(&banByIP); + } + if (!nodeUUID.isNull() && nodeUUID != sendingNode->getUUID()) { // make sure we actually have a node with this UUID auto limitedNodeList = DependencyManager::get(); @@ -881,24 +893,40 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetPermissions().getKey()]; - - newPermissions = !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); - - // ensure that the connect permission is clear - userPermissions->clear(NodePermissions::Permission::canConnectToDomain); + // if we have optional ban parameters, we should ban the username based on the parameter + if (hasOptionalBanParameters) { + if (banByUsername) { + // check if there were already permissions + bool hadPermissions = havePermissionsForName(verifiedUsername); + + // grab or create permissions for the given username + auto userPermissions = _agentPermissions[matchingNode->getPermissions().getKey()]; + + newPermissions = !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); + + // ensure that the connect permission is clear + userPermissions->clear(NodePermissions::Permission::canConnectToDomain); + } + } else { + // check if there were already permissions + bool hadPermissions = havePermissionsForName(verifiedUsername); + + // grab or create permissions for the given username + auto userPermissions = _agentPermissions[matchingNode->getPermissions().getKey()]; + + newPermissions = !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); + + // ensure that the connect permission is clear + userPermissions->clear(NodePermissions::Permission::canConnectToDomain); + } } // if we didn't have a username, or this domain-server uses the "multi-kick" setting to // kick logged in users via username AND machine fingerprint (or IP as fallback) // then we remove connect permissions for the machine fingerprint (or IP as fallback) const QString MULTI_KICK_SETTINGS_KEYPATH = "security.multi_kick_logged_in"; - - if (verifiedUsername.isEmpty() || valueOrDefaultValueForKeyPath(MULTI_KICK_SETTINGS_KEYPATH).toBool()) { + qDebug() << "verifiedUsername.isEmpty()" << verifiedUsername.isEmpty(); + if (banByFingerprint || verifiedUsername.isEmpty() || valueOrDefaultValueForKeyPath(MULTI_KICK_SETTINGS_KEYPATH).toBool()) { // remove connect permissions for the machine fingerprint DomainServerNodeData* nodeData = static_cast(matchingNode->getLinkedData()); if (nodeData) { @@ -923,36 +951,39 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointerclear(NodePermissions::Permission::canConnectToDomain); } } else { - // if no node data, all we can do is IP address - auto& kickAddress = matchingNode->getActiveSocket() - ? matchingNode->getActiveSocket()->getAddress() - : matchingNode->getPublicSocket().getAddress(); + // if no node data, all we can do is ban by IP address + banByIP = true; + } + } + + if (banByIP) { + auto& kickAddress = matchingNode->getActiveSocket() + ? matchingNode->getActiveSocket()->getAddress() + : matchingNode->getPublicSocket().getAddress(); - // probably isLoopback covers it, as whenever I try to ban an agent on same machine as the domain-server - // it is always 127.0.0.1, but looking at the public and local addresses just to be sure - // TODO: soon we will have feedback (in the form of a message to the client) after we kick. When we - // do, we will have a success flag, and perhaps a reason for failure. For now, just don't do it. - if (kickAddress == limitedNodeList->getPublicSockAddr().getAddress() || - kickAddress == limitedNodeList->getLocalSockAddr().getAddress() || - kickAddress.isLoopback() ) { - qWarning() << "attempt to kick node running on same machine as domain server, ignoring KickRequest"; - return; - } + // probably isLoopback covers it, as whenever I try to ban an agent on same machine as the domain-server + // it is always 127.0.0.1, but looking at the public and local addresses just to be sure + // TODO: soon we will have feedback (in the form of a message to the client) after we kick. When we + // do, we will have a success flag, and perhaps a reason for failure. For now, just don't do it. + if (kickAddress == limitedNodeList->getPublicSockAddr().getAddress() || + kickAddress == limitedNodeList->getLocalSockAddr().getAddress() || + kickAddress.isLoopback() ) { + qWarning() << "attempt to kick node running on same machine as domain server, ignoring KickRequest"; + return; + } + NodePermissionsKey ipAddressKey(kickAddress.toString(), QUuid()); - NodePermissionsKey ipAddressKey(kickAddress.toString(), QUuid()); + // check if there were already permissions for the IP + bool hadIPPermissions = hasPermissionsForIP(kickAddress); - // check if there were already permissions for the IP - bool hadIPPermissions = hasPermissionsForIP(kickAddress); + // grab or create permissions for the given IP address + auto ipPermissions = _ipPermissions[ipAddressKey]; - // grab or create permissions for the given IP address - auto ipPermissions = _ipPermissions[ipAddressKey]; + if (!hadIPPermissions || ipPermissions->can(NodePermissions::Permission::canConnectToDomain)) { + newPermissions = true; - if (!hadIPPermissions || ipPermissions->can(NodePermissions::Permission::canConnectToDomain)) { - newPermissions = true; - - ipPermissions->clear(NodePermissions::Permission::canConnectToDomain); - } + ipPermissions->clear(NodePermissions::Permission::canConnectToDomain); } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eec1efbd99..f2e17c8dc1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2493,7 +2493,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return viewFrustum.getPosition(); }); - DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID) { userKickConfirmation(nodeID); }); + DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { userKickConfirmation(nodeID, banByUsername, banByFingerprint, banByIP); }); render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; @@ -3575,7 +3575,7 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { _desktopRootItemCreated = true; } -void Application::userKickConfirmation(const QUuid& nodeID) { +void Application::userKickConfirmation(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { auto avatarHashMap = DependencyManager::get(); auto avatar = avatarHashMap->getAvatarBySessionID(nodeID); @@ -3600,7 +3600,7 @@ void Application::userKickConfirmation(const QUuid& nodeID) { // ask the NodeList to kick the user with the given session ID if (yes) { - DependencyManager::get()->kickNodeBySessionID(nodeID); + DependencyManager::get()->kickNodeBySessionID(nodeID, banByUsername, banByFingerprint, banByIP); } DependencyManager::get()->setWaitForKickResponse(false); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5cb5fdd5c0..65638b92db 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -608,7 +608,7 @@ private: void toggleTabletUI(bool shouldOpen = false) const; bool shouldCaptureMouse() const; - void userKickConfirmation(const QUuid& nodeID); + void userKickConfirmation(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP); MainWindow* _window; QElapsedTimer& _sessionRunTimer; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index a523a7ff36..6f3f774452 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -1263,17 +1263,21 @@ float NodeList::getInjectorGain() { return _injectorGain; } -void NodeList::kickNodeBySessionID(const QUuid& nodeID) { +void NodeList::kickNodeBySessionID(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { // send a request to domain-server to kick the node with the given session ID // the domain-server will handle the persistence of the kick (via username or IP) if (!nodeID.isNull() && getSessionUUID() != nodeID ) { if (getThisNodeCanKick()) { // setup the packet - auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID, true); + auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID + (sizeof(bool) * 3), true); // write the node ID to the packet kickPacket->write(nodeID.toRfc4122()); + // write the ban parameters to the packet + kickPacket->writePrimitive(banByUsername); + kickPacket->writePrimitive(banByFingerprint); + kickPacket->writePrimitive(banByIP); qCDebug(networking) << "Sending packet to kick node" << uuidStringWithoutCurlyBraces(nodeID); diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 4954c53c84..3573db1b9f 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -86,7 +86,7 @@ public: void setInjectorGain(float gain); float getInjectorGain(); - void kickNodeBySessionID(const QUuid& nodeID); + void kickNodeBySessionID(const QUuid& nodeID, bool banByUsername = true, bool banByFingerprint = true, bool banByIP = false); void muteNodeBySessionID(const QUuid& nodeID); void requestUsernameFromSessionID(const QUuid& nodeID); bool getRequestsDomainListData() { return _requestsDomainListData; } diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 9beb52f20a..c22c1d270e 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2016-07-11. // Copyright 2016 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -51,15 +52,15 @@ float UsersScriptingInterface::getAvatarGain(const QUuid& nodeID) { return DependencyManager::get()->getAvatarGain(nodeID); } -void UsersScriptingInterface::kick(const QUuid& nodeID) { +void UsersScriptingInterface::kick(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { if (_kickConfirmationOperator) { bool waitingForKickResponse = _kickResponseLock.resultWithReadLock([&] { return _waitingForKickResponse; }); if (getCanKick() && !waitingForKickResponse) { - _kickConfirmationOperator(nodeID); + _kickConfirmationOperator(nodeID, banByUsername, banByFingerprint, banByIP); } } else { - DependencyManager::get()->kickNodeBySessionID(nodeID); + DependencyManager::get()->kickNodeBySessionID(nodeID, banByUsername, banByFingerprint, banByIP); } } diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 3b0666481a..ad86189afa 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2016-07-11. // Copyright 2016 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -41,7 +42,7 @@ class UsersScriptingInterface : public QObject, public Dependency { public: UsersScriptingInterface(); - void setKickConfirmationOperator(std::function kickConfirmationOperator) { + void setKickConfirmationOperator(std::function kickConfirmationOperator) { _kickConfirmationOperator = kickConfirmationOperator; } @@ -112,12 +113,15 @@ public slots: /**jsdoc * Kicks and bans a user. This removes them from the server and prevents them from returning. The ban is by user name if - * available, or machine fingerprint otherwise. + * available and by machine fingerprint. *

This function only works if you're an administrator of the domain you're in.

* @function Users.kick * @param {Uuid} sessionID - The session ID of the user to kick and ban. + * @param {boolean} [banByUsername=true] - Should ban the user's username. + * @param {boolean} [banByFingerprint=true] - Should ban the user's machine fingerprint. + * @param {boolean} [banByIP=false] - Should ban the user's IP address. */ - void kick(const QUuid& nodeID); + void kick(const QUuid& nodeID, bool banByUsername = true, bool banByFingerprint = true, bool banByIP = false); /**jsdoc * Mutes a user's microphone for everyone. The mute is not permanent: the user can unmute themselves. @@ -237,7 +241,7 @@ private: bool getRequestsDomainListData(); void setRequestsDomainListData(bool requests); - std::function _kickConfirmationOperator; + std::function _kickConfirmationOperator; ReadWriteLockable _kickResponseLock; bool _waitingForKickResponse { false }; From 712b5e508833b736e4af51a024ae391055cc7556 Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Thu, 11 Mar 2021 17:06:07 -0500 Subject: [PATCH 02/12] Update DomainServerSettingsManager.cpp --- domain-server/src/DomainServerSettingsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 8d1a479407..0b0db28876 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -925,7 +925,7 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer(matchingNode->getLinkedData()); From 0216b3468119bdd0b3fdceaec6f5dcb1b70dfe06 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Wed, 17 Mar 2021 19:37:06 -0400 Subject: [PATCH 03/12] State of refactoring --- .../src/DomainServerSettingsManager.cpp | 39 +++++++------------ interface/src/Application.cpp | 6 +-- interface/src/Application.h | 2 +- libraries/networking/src/NodeList.cpp | 20 +++++++--- libraries/networking/src/NodeList.h | 2 +- .../UserActivityLoggerScriptingInterface.h | 1 + .../src/UsersScriptingInterface.cpp | 7 ++-- .../src/UsersScriptingInterface.h | 14 +++++-- libraries/shared/src/ModerationFlags.h | 28 +++++++++++++ 9 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 libraries/shared/src/ModerationFlags.h diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 0b0db28876..0f5f4741d9 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "DomainServerNodeData.h" @@ -864,15 +865,17 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointerreadWithoutCopy(NUM_BYTES_RFC4122_UUID)); bool hasOptionalBanParameters = false; - bool banByUsername = false; - bool banByFingerprint = false; - bool banByIP = false; + int banParameters; + bool banByUsername; + bool banByFingerprint; + bool banByIP; // pull optional ban parameters from the packet if (message.data()->getSize() > NUM_BYTES_RFC4122_UUID) { hasOptionalBanParameters = true; - message->readPrimitive(&banByUsername); - message->readPrimitive(&banByFingerprint); - message->readPrimitive(&banByIP); + message->readPrimitive(&banParameters); + banByUsername = banParameters & ModerationFlags::BanFlags::BAN_BY_USERNAME; + banByFingerprint = banParameters & ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; + banByIP = banParameters & ModerationFlags::BanFlags::BAN_BY_IP; } if (!nodeUUID.isNull() && nodeUUID != sendingNode->getUUID()) { @@ -894,28 +897,16 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetPermissions().getKey()]; - - newPermissions = !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); - - // ensure that the connect permission is clear - userPermissions->clear(NodePermissions::Permission::canConnectToDomain); - } - } else { + if (!hasOptionalBanParameters || banByUsername) { // check if there were already permissions bool hadPermissions = havePermissionsForName(verifiedUsername); - + // grab or create permissions for the given username auto userPermissions = _agentPermissions[matchingNode->getPermissions().getKey()]; - - newPermissions = !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); - + + newPermissions = + !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); + // ensure that the connect permission is clear userPermissions->clear(NodePermissions::Permission::canConnectToDomain); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f2e17c8dc1..18f993f2f7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2493,7 +2493,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return viewFrustum.getPosition(); }); - DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { userKickConfirmation(nodeID, banByUsername, banByFingerprint, banByIP); }); + DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, int banFlags) { userKickConfirmation(nodeID, banFlags); }); render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; @@ -3575,7 +3575,7 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { _desktopRootItemCreated = true; } -void Application::userKickConfirmation(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { +void Application::userKickConfirmation(const QUuid& nodeID, int banFlags) { auto avatarHashMap = DependencyManager::get(); auto avatar = avatarHashMap->getAvatarBySessionID(nodeID); @@ -3600,7 +3600,7 @@ void Application::userKickConfirmation(const QUuid& nodeID, bool banByUsername, // ask the NodeList to kick the user with the given session ID if (yes) { - DependencyManager::get()->kickNodeBySessionID(nodeID, banByUsername, banByFingerprint, banByIP); + DependencyManager::get()->kickNodeBySessionID(nodeID, banFlags); } DependencyManager::get()->setWaitForKickResponse(false); diff --git a/interface/src/Application.h b/interface/src/Application.h index 65638b92db..aa2c62658e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -608,7 +608,7 @@ private: void toggleTabletUI(bool shouldOpen = false) const; bool shouldCaptureMouse() const; - void userKickConfirmation(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP); + void userKickConfirmation(const QUuid& nodeID, int banFlags); MainWindow* _window; QElapsedTimer& _sessionRunTimer; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 6f3f774452..e67423a24a 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -42,6 +42,7 @@ #include "udt/PacketHeaders.h" #include "SharedUtil.h" #include +#include using namespace std::chrono; @@ -1263,21 +1264,30 @@ float NodeList::getInjectorGain() { return _injectorGain; } -void NodeList::kickNodeBySessionID(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { +void NodeList::kickNodeBySessionID(const QUuid& nodeID, int banFlags) { // send a request to domain-server to kick the node with the given session ID // the domain-server will handle the persistence of the kick (via username or IP) if (!nodeID.isNull() && getSessionUUID() != nodeID ) { if (getThisNodeCanKick()) { // setup the packet - auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID + (sizeof(bool) * 3), true); + auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID + sizeof(int), true); + + //int banParameters {}; + //if (banByUsername) { + // banParameters |= ModerationFlags::BanFlags::BAN_BY_USERNAME; + //} + //if (banByFingerprint) { + // banParameters |= ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; + //} + //if (banByIP) { + // banParameters |= ModerationFlags::BanFlags::BAN_BY_IP; + //} // write the node ID to the packet kickPacket->write(nodeID.toRfc4122()); // write the ban parameters to the packet - kickPacket->writePrimitive(banByUsername); - kickPacket->writePrimitive(banByFingerprint); - kickPacket->writePrimitive(banByIP); + kickPacket->writePrimitive(banFlags); qCDebug(networking) << "Sending packet to kick node" << uuidStringWithoutCurlyBraces(nodeID); diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 3573db1b9f..673b5dab55 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -86,7 +86,7 @@ public: void setInjectorGain(float gain); float getInjectorGain(); - void kickNodeBySessionID(const QUuid& nodeID, bool banByUsername = true, bool banByFingerprint = true, bool banByIP = false); + void kickNodeBySessionID(const QUuid& nodeID, int banFlags); void muteNodeBySessionID(const QUuid& nodeID); void requestUsernameFromSessionID(const QUuid& nodeID); bool getRequestsDomainListData() { return _requestsDomainListData; } diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index 1cda1235e9..94e1590e88 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -1,3 +1,4 @@ + // // UserActivityLoggerScriptingInterface.h // libraries/networking/src diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index c22c1d270e..9b580528d5 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -52,15 +52,14 @@ float UsersScriptingInterface::getAvatarGain(const QUuid& nodeID) { return DependencyManager::get()->getAvatarGain(nodeID); } -void UsersScriptingInterface::kick(const QUuid& nodeID, bool banByUsername, bool banByFingerprint, bool banByIP) { - +void UsersScriptingInterface::kick(const QUuid& nodeID, int banFlags) { if (_kickConfirmationOperator) { bool waitingForKickResponse = _kickResponseLock.resultWithReadLock([&] { return _waitingForKickResponse; }); if (getCanKick() && !waitingForKickResponse) { - _kickConfirmationOperator(nodeID, banByUsername, banByFingerprint, banByIP); + _kickConfirmationOperator(nodeID, banFlags); } } else { - DependencyManager::get()->kickNodeBySessionID(nodeID, banByUsername, banByFingerprint, banByIP); + DependencyManager::get()->kickNodeBySessionID(nodeID, banFlags); } } diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index ad86189afa..c103508719 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -17,6 +17,7 @@ #include #include +#include /**jsdoc * The Users API provides features to regulate your interaction with other users. @@ -40,9 +41,14 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_PROPERTY(bool canKick READ getCanKick) Q_PROPERTY(bool requestsDomainListData READ getRequestsDomainListData WRITE setRequestsDomainListData) + Q_PROPERTY(unsigned int NO_BAN READ ModerationFlags::BanFlags::NO_BAN CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_USERNAME READ ModerationFlags::BanFlags::BAN_BY_USERNAME CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_FINGERPRINT READ ModerationFlags::BanFlags::BAN_BY_FINGERPRINT CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_IP READ ModerationFlags::BanFlags::BAN_BY_IP CONSTANT) + public: UsersScriptingInterface(); - void setKickConfirmationOperator(std::function kickConfirmationOperator) { + void setKickConfirmationOperator(std::function kickConfirmationOperator) { _kickConfirmationOperator = kickConfirmationOperator; } @@ -113,7 +119,7 @@ public slots: /**jsdoc * Kicks and bans a user. This removes them from the server and prevents them from returning. The ban is by user name if - * available and by machine fingerprint. + * available and by machine fingerprint. The ban functionality can be controlled with flags. *

This function only works if you're an administrator of the domain you're in.

* @function Users.kick * @param {Uuid} sessionID - The session ID of the user to kick and ban. @@ -121,7 +127,7 @@ public slots: * @param {boolean} [banByFingerprint=true] - Should ban the user's machine fingerprint. * @param {boolean} [banByIP=false] - Should ban the user's IP address. */ - void kick(const QUuid& nodeID, bool banByUsername = true, bool banByFingerprint = true, bool banByIP = false); + void kick(const QUuid& nodeID, int banFlags = 0); /**jsdoc * Mutes a user's microphone for everyone. The mute is not permanent: the user can unmute themselves. @@ -241,7 +247,7 @@ private: bool getRequestsDomainListData(); void setRequestsDomainListData(bool requests); - std::function _kickConfirmationOperator; + std::function _kickConfirmationOperator; ReadWriteLockable _kickResponseLock; bool _waitingForKickResponse { false }; diff --git a/libraries/shared/src/ModerationFlags.h b/libraries/shared/src/ModerationFlags.h new file mode 100644 index 0000000000..3930f65e28 --- /dev/null +++ b/libraries/shared/src/ModerationFlags.h @@ -0,0 +1,28 @@ +// +// ModerationFlags.h +// libraries/shared/src +// +// Created by Kalila L. on Mar 11 2021. +// Copyright 2021 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef vircadia_ModerationFlags_h +#define vircadia_ModerationFlags_h + +class ModerationFlags { +public: + enum BanFlags + { + NO_BAN = 0, + BAN_BY_USERNAME = 1, + BAN_BY_FINGERPRINT = 2, + BAN_BY_IP = 4 + }; + + int test(int lol) { return lol; }; +}; + +#endif // vircadia_ModerationFlags_h \ No newline at end of file From be0bd3940d8542b4c039672131184f7b256768de Mon Sep 17 00:00:00 2001 From: Kalila L Date: Wed, 17 Mar 2021 23:25:08 -0400 Subject: [PATCH 04/12] Finish flag work on kick functionality. --- interface/src/Application.h | 3 ++- .../src/UsersScriptingInterface.h | 19 +++++++++++-------- libraries/shared/src/ModerationFlags.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index aa2c62658e..cb1230c850 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -50,6 +50,7 @@ #include #include #include +#include #include "avatar/MyAvatar.h" #include "FancyCamera.h" @@ -608,7 +609,7 @@ private: void toggleTabletUI(bool shouldOpen = false) const; bool shouldCaptureMouse() const; - void userKickConfirmation(const QUuid& nodeID, int banFlags); + void userKickConfirmation(const QUuid& nodeID, int banFlags = ModerationFlags::getDefaultBanFlags()); MainWindow* _window; QElapsedTimer& _sessionRunTimer; diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index c103508719..42e63cdbf1 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -41,10 +41,10 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_PROPERTY(bool canKick READ getCanKick) Q_PROPERTY(bool requestsDomainListData READ getRequestsDomainListData WRITE setRequestsDomainListData) - Q_PROPERTY(unsigned int NO_BAN READ ModerationFlags::BanFlags::NO_BAN CONSTANT) - Q_PROPERTY(unsigned int BAN_BY_USERNAME READ ModerationFlags::BanFlags::BAN_BY_USERNAME CONSTANT) - Q_PROPERTY(unsigned int BAN_BY_FINGERPRINT READ ModerationFlags::BanFlags::BAN_BY_FINGERPRINT CONSTANT) - Q_PROPERTY(unsigned int BAN_BY_IP READ ModerationFlags::BanFlags::BAN_BY_IP CONSTANT) + Q_PROPERTY(unsigned int NO_BAN READ getNoBan CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_USERNAME READ getBanByUsername CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_FINGERPRINT READ getBanByFingerprint CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_IP READ getBanByIP CONSTANT) public: UsersScriptingInterface(); @@ -123,11 +123,9 @@ public slots: *

This function only works if you're an administrator of the domain you're in.

* @function Users.kick * @param {Uuid} sessionID - The session ID of the user to kick and ban. - * @param {boolean} [banByUsername=true] - Should ban the user's username. - * @param {boolean} [banByFingerprint=true] - Should ban the user's machine fingerprint. - * @param {boolean} [banByIP=false] - Should ban the user's IP address. + * @param {number} - Preferred ban flags. Bans a user by username (if available) and machine fingerprint by default. */ - void kick(const QUuid& nodeID, int banFlags = 0); + void kick(const QUuid& nodeID, int banFlags = ModerationFlags::getDefaultBanFlags()); /**jsdoc * Mutes a user's microphone for everyone. The mute is not permanent: the user can unmute themselves. @@ -247,6 +245,11 @@ private: bool getRequestsDomainListData(); void setRequestsDomainListData(bool requests); + static constexpr unsigned int getNoBan() { return ModerationFlags::BanFlags::NO_BAN; }; + static constexpr unsigned int getBanByUsername() { return ModerationFlags::BanFlags::BAN_BY_USERNAME; }; + static constexpr unsigned int getBanByFingerprint() { return ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; }; + static constexpr unsigned int getBanByIP() { return ModerationFlags::BanFlags::BAN_BY_IP; }; + std::function _kickConfirmationOperator; ReadWriteLockable _kickResponseLock; diff --git a/libraries/shared/src/ModerationFlags.h b/libraries/shared/src/ModerationFlags.h index 3930f65e28..2724e353e6 100644 --- a/libraries/shared/src/ModerationFlags.h +++ b/libraries/shared/src/ModerationFlags.h @@ -22,7 +22,7 @@ public: BAN_BY_IP = 4 }; - int test(int lol) { return lol; }; + static constexpr unsigned int getDefaultBanFlags() { return (BanFlags::BAN_BY_USERNAME | BanFlags::BAN_BY_FINGERPRINT); }; }; #endif // vircadia_ModerationFlags_h \ No newline at end of file From c6c3dc66ea8b7e3dd6b6ef265acd40bee3015336 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Thu, 18 Mar 2021 01:39:13 -0400 Subject: [PATCH 05/12] Add IP ban button to the "People" app. --- interface/resources/qml/hifi/Pal.qml | 39 ++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 55f2bb80b1..67ba8bd7aa 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -506,6 +506,7 @@ Rectangle { id: itemCell; property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore"; property bool isButton: styleData.role === "mute" || styleData.role === "kick"; + property bool isBan: styleData.role === "kick"; property bool isAvgAudio: styleData.role === "avgAudioLevel"; opacity: !isButton ? (model && model.isPresent ? 1.0 : 0.4) : 1.0; // Admin actions shouldn't turn gray @@ -605,7 +606,9 @@ Rectangle { color: 2; // Red visible: isButton; enabled: !nameCard.isReplicated; - anchors.centerIn: parent; + anchors.verticalCenter: itemCell.verticalCenter; + anchors.left: parent.left; + anchors.leftMargin: styleData.role === "kick" ? 4 : 18; width: 32; height: 32; onClicked: { @@ -620,7 +623,39 @@ Rectangle { HiFiGlyphs { text: (styleData.role === "kick") ? hifi.glyphs.error : hifi.glyphs.muted; // Size - size: parent.height*1.3; + size: parent.height * 1.3; + // Anchors + anchors.fill: parent; + // Style + horizontalAlignment: Text.AlignHCenter; + color: enabled ? hifi.buttons.textColor[actionButton.color] + : hifi.buttons.disabledTextColor[actionButton.colorScheme]; + } + } + + HifiControlsUit.Button { + id: hardBanButton; + color: 2; // Red + visible: isBan; + enabled: !nameCard.isReplicated; + anchors.verticalCenter: itemCell.verticalCenter; + anchors.left: parent.left; + anchors.leftMargin: actionButton.width + 14; + width: 32; + height: 32; + onClicked: { + Users[styleData.role](model.sessionId, 7); // Ban params add up to 7 from Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP + UserActivityLogger["palAction"](styleData.role, model.sessionId); + if (styleData.role === "kick") { + nearbyUserModelData.splice(model.userIndex, 1); + nearbyUserModel.remove(model.userIndex); // after changing nearbyUserModelData, b/c ListModel can frob the data + } + } + // muted/error glyphs + HiFiGlyphs { + text: hifi.glyphs.alert; + // Size + size: parent.height * 1.3; // Anchors anchors.fill: parent; // Style From da7bcf15846d764d45449e1af907438033242097 Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Thu, 18 Mar 2021 17:53:21 -0400 Subject: [PATCH 06/12] Update NodeList.cpp --- libraries/networking/src/NodeList.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e67423a24a..b6660e6c59 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -1273,17 +1273,6 @@ void NodeList::kickNodeBySessionID(const QUuid& nodeID, int banFlags) { // setup the packet auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID + sizeof(int), true); - //int banParameters {}; - //if (banByUsername) { - // banParameters |= ModerationFlags::BanFlags::BAN_BY_USERNAME; - //} - //if (banByFingerprint) { - // banParameters |= ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; - //} - //if (banByIP) { - // banParameters |= ModerationFlags::BanFlags::BAN_BY_IP; - //} - // write the node ID to the packet kickPacket->write(nodeID.toRfc4122()); // write the ban parameters to the packet From 9dadc44f6ce93072b4afa844f4b0b13144b909b4 Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Thu, 18 Mar 2021 17:57:49 -0400 Subject: [PATCH 07/12] Update UserActivityLoggerScriptingInterface.h --- libraries/networking/src/UserActivityLoggerScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index 94e1590e88..ea01a8446c 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -1,10 +1,10 @@ - // // UserActivityLoggerScriptingInterface.h // libraries/networking/src // // Created by Ryan Huffman on 6/06/16. // Copyright 2016 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From fd592dfb061afe2e52a04c293426620dc09bb329 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Fri, 19 Mar 2021 04:11:26 -0400 Subject: [PATCH 08/12] CR. --- domain-server/src/DomainServerSettingsManager.cpp | 2 +- interface/resources/qml/hifi/Pal.qml | 2 +- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 +- libraries/networking/src/NodeList.cpp | 2 +- libraries/networking/src/NodeList.h | 2 +- libraries/script-engine/src/UsersScriptingInterface.cpp | 2 +- libraries/script-engine/src/UsersScriptingInterface.h | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 0f5f4741d9..b113c28318 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -870,7 +870,7 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetSize() > NUM_BYTES_RFC4122_UUID) { + if (message.data()->getSize() == (NUM_BYTES_RFC4122_UUID + sizeof(int))) { hasOptionalBanParameters = true; message->readPrimitive(&banParameters); banByUsername = banParameters & ModerationFlags::BanFlags::BAN_BY_USERNAME; diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 67ba8bd7aa..d35ae5ea90 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -644,7 +644,7 @@ Rectangle { width: 32; height: 32; onClicked: { - Users[styleData.role](model.sessionId, 7); // Ban params add up to 7 from Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP + Users[styleData.role](model.sessionId, Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP); // Ban params add up to 7 from Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP UserActivityLogger["palAction"](styleData.role, model.sessionId); if (styleData.role === "kick") { nearbyUserModelData.splice(model.userIndex, 1); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 18f993f2f7..59371176be 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2493,7 +2493,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return viewFrustum.getPosition(); }); - DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, int banFlags) { userKickConfirmation(nodeID, banFlags); }); + DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, unsigned int banFlags) { userKickConfirmation(nodeID, banFlags); }); render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; @@ -3575,7 +3575,7 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { _desktopRootItemCreated = true; } -void Application::userKickConfirmation(const QUuid& nodeID, int banFlags) { +void Application::userKickConfirmation(const QUuid& nodeID, unsigned int banFlags) { auto avatarHashMap = DependencyManager::get(); auto avatar = avatarHashMap->getAvatarBySessionID(nodeID); diff --git a/interface/src/Application.h b/interface/src/Application.h index cb1230c850..18f90e8db9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -609,7 +609,7 @@ private: void toggleTabletUI(bool shouldOpen = false) const; bool shouldCaptureMouse() const; - void userKickConfirmation(const QUuid& nodeID, int banFlags = ModerationFlags::getDefaultBanFlags()); + void userKickConfirmation(const QUuid& nodeID, unsigned int banFlags = ModerationFlags::getDefaultBanFlags()); MainWindow* _window; QElapsedTimer& _sessionRunTimer; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index b6660e6c59..45df4d57f9 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -1264,7 +1264,7 @@ float NodeList::getInjectorGain() { return _injectorGain; } -void NodeList::kickNodeBySessionID(const QUuid& nodeID, int banFlags) { +void NodeList::kickNodeBySessionID(const QUuid& nodeID, unsigned int banFlags) { // send a request to domain-server to kick the node with the given session ID // the domain-server will handle the persistence of the kick (via username or IP) diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 673b5dab55..c861dd26e7 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -86,7 +86,7 @@ public: void setInjectorGain(float gain); float getInjectorGain(); - void kickNodeBySessionID(const QUuid& nodeID, int banFlags); + void kickNodeBySessionID(const QUuid& nodeID, unsigned int banFlags); void muteNodeBySessionID(const QUuid& nodeID); void requestUsernameFromSessionID(const QUuid& nodeID); bool getRequestsDomainListData() { return _requestsDomainListData; } diff --git a/libraries/script-engine/src/UsersScriptingInterface.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 9b580528d5..883c728c2f 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -52,7 +52,7 @@ float UsersScriptingInterface::getAvatarGain(const QUuid& nodeID) { return DependencyManager::get()->getAvatarGain(nodeID); } -void UsersScriptingInterface::kick(const QUuid& nodeID, int banFlags) { +void UsersScriptingInterface::kick(const QUuid& nodeID, unsigned int banFlags) { if (_kickConfirmationOperator) { bool waitingForKickResponse = _kickResponseLock.resultWithReadLock([&] { return _waitingForKickResponse; }); if (getCanKick() && !waitingForKickResponse) { diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 42e63cdbf1..e61c8734f3 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -48,7 +48,7 @@ class UsersScriptingInterface : public QObject, public Dependency { public: UsersScriptingInterface(); - void setKickConfirmationOperator(std::function kickConfirmationOperator) { + void setKickConfirmationOperator(std::function kickConfirmationOperator) { _kickConfirmationOperator = kickConfirmationOperator; } @@ -125,7 +125,7 @@ public slots: * @param {Uuid} sessionID - The session ID of the user to kick and ban. * @param {number} - Preferred ban flags. Bans a user by username (if available) and machine fingerprint by default. */ - void kick(const QUuid& nodeID, int banFlags = ModerationFlags::getDefaultBanFlags()); + void kick(const QUuid& nodeID, unsigned int banFlags = ModerationFlags::getDefaultBanFlags()); /**jsdoc * Mutes a user's microphone for everyone. The mute is not permanent: the user can unmute themselves. @@ -250,7 +250,7 @@ private: static constexpr unsigned int getBanByFingerprint() { return ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; }; static constexpr unsigned int getBanByIP() { return ModerationFlags::BanFlags::BAN_BY_IP; }; - std::function _kickConfirmationOperator; + std::function _kickConfirmationOperator; ReadWriteLockable _kickResponseLock; bool _waitingForKickResponse { false }; From f067feb37a5f19bd4a1ab314447c307c4d91af31 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Fri, 19 Mar 2021 04:44:58 -0400 Subject: [PATCH 09/12] Add docs for ban functionality. --- .../script-engine/src/UsersScriptingInterface.h | 8 ++++++-- libraries/shared/src/ModerationFlags.h | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index e61c8734f3..a02553eca8 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -33,6 +33,10 @@ * false. Read-only. * @property {boolean} requestsDomainListData - true if the client requests extra data from the mixers (such as * positional data of an avatar they've ignored). Read-only. + * @property {BanFlags} NO_BAN - Do not ban person. Read-only. + * @property {BanFlags} BAN_BY_USERNAME - Ban person by username. Read-only. + * @property {BanFlags} BAN_BY_FINGERPRINT - Ban person by fingerprint. Read-only. + * @property {BanFlags} BAN_BY_IP - Ban person by IP address. Read-only. */ class UsersScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -118,8 +122,8 @@ public slots: float getAvatarGain(const QUuid& nodeID); /**jsdoc - * Kicks and bans a user. This removes them from the server and prevents them from returning. The ban is by user name if - * available and by machine fingerprint. The ban functionality can be controlled with flags. + * Kicks and bans a user. This removes them from the server and prevents them from returning. The ban is by user name (if + * available) and by machine fingerprint. The ban functionality can be controlled with flags. *

This function only works if you're an administrator of the domain you're in.

* @function Users.kick * @param {Uuid} sessionID - The session ID of the user to kick and ban. diff --git a/libraries/shared/src/ModerationFlags.h b/libraries/shared/src/ModerationFlags.h index 2724e353e6..9bdd4bfbea 100644 --- a/libraries/shared/src/ModerationFlags.h +++ b/libraries/shared/src/ModerationFlags.h @@ -14,6 +14,23 @@ class ModerationFlags { public: + + /**jsdoc + *

A set of flags for moderation ban actions. The value is constructed by using the | (bitwise OR) operator on the + * individual flag values.

+ * + * + * + * + * + * + * + * + * + * + *
Flag NameValueDescription
NO_BAN0Don't ban user when kicking. This does not currently have an effect.
BAN_BY_USERNAME1Ban the person by their username.
BAN_BY_FINGERPRINT2Ban the person by their machine fingerprint.
BAN_BY_IP4Ban the person by their IP address.
+ * @typedef {number} BanFlags + */ enum BanFlags { NO_BAN = 0, From 6f7bfbc053b35cee123004541d6c56fab8afde4d Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Sun, 21 Mar 2021 03:01:28 -0400 Subject: [PATCH 10/12] Update Pal.qml --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index d35ae5ea90..15425ec15c 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -644,7 +644,7 @@ Rectangle { width: 32; height: 32; onClicked: { - Users[styleData.role](model.sessionId, Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP); // Ban params add up to 7 from Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP + Users[styleData.role](model.sessionId, Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP); UserActivityLogger["palAction"](styleData.role, model.sessionId); if (styleData.role === "kick") { nearbyUserModelData.splice(model.userIndex, 1); From 12d5687c6a6c7cccde6d06e4dca3d8010b7e054a Mon Sep 17 00:00:00 2001 From: Kalila <69767640+digisomni@users.noreply.github.com> Date: Sun, 21 Mar 2021 13:13:24 -0400 Subject: [PATCH 11/12] Update libraries/script-engine/src/UsersScriptingInterface.h Co-authored-by: David Rowe --- libraries/script-engine/src/UsersScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index a02553eca8..0b3e9dc683 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -127,7 +127,7 @@ public slots: *

This function only works if you're an administrator of the domain you're in.

* @function Users.kick * @param {Uuid} sessionID - The session ID of the user to kick and ban. - * @param {number} - Preferred ban flags. Bans a user by username (if available) and machine fingerprint by default. + * @param {BanFlags} - Preferred ban flags. Bans a user by username (if available) and machine fingerprint by default. */ void kick(const QUuid& nodeID, unsigned int banFlags = ModerationFlags::getDefaultBanFlags()); From cfac34bf7e7bc60d23b8ece6569875976802f313 Mon Sep 17 00:00:00 2001 From: Kalila L Date: Sun, 21 Mar 2021 13:20:05 -0400 Subject: [PATCH 12/12] CR. --- libraries/script-engine/src/UsersScriptingInterface.h | 8 ++++---- libraries/shared/src/ModerationFlags.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 0b3e9dc683..79c0f4b61d 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -33,10 +33,10 @@ * false. Read-only. * @property {boolean} requestsDomainListData - true if the client requests extra data from the mixers (such as * positional data of an avatar they've ignored). Read-only. - * @property {BanFlags} NO_BAN - Do not ban person. Read-only. - * @property {BanFlags} BAN_BY_USERNAME - Ban person by username. Read-only. - * @property {BanFlags} BAN_BY_FINGERPRINT - Ban person by fingerprint. Read-only. - * @property {BanFlags} BAN_BY_IP - Ban person by IP address. Read-only. + * @property {BanFlags} NO_BAN - Do not ban user. Read-only. + * @property {BanFlags} BAN_BY_USERNAME - Ban user by username. Read-only. + * @property {BanFlags} BAN_BY_FINGERPRINT - Ban user by fingerprint. Read-only. + * @property {BanFlags} BAN_BY_IP - Ban user by IP address. Read-only. */ class UsersScriptingInterface : public QObject, public Dependency { Q_OBJECT diff --git a/libraries/shared/src/ModerationFlags.h b/libraries/shared/src/ModerationFlags.h index 9bdd4bfbea..a8390873d7 100644 --- a/libraries/shared/src/ModerationFlags.h +++ b/libraries/shared/src/ModerationFlags.h @@ -42,4 +42,4 @@ public: static constexpr unsigned int getDefaultBanFlags() { return (BanFlags::BAN_BY_USERNAME | BanFlags::BAN_BY_FINGERPRINT); }; }; -#endif // vircadia_ModerationFlags_h \ No newline at end of file +#endif // vircadia_ModerationFlags_h