represent node permissions as a bitfield rather than a list of bools

This commit is contained in:
Seth Alves 2016-06-27 14:55:13 -07:00
parent c7d56493b1
commit d4cc4bf1e4
10 changed files with 116 additions and 105 deletions

View file

@ -409,7 +409,7 @@
"label": "Connect",
"type": "checkbox",
"editable": true,
"default": true
"default": false
},
{
"name": "id_can_adjust_locks",
@ -478,7 +478,7 @@
"label": "Connect",
"type": "checkbox",
"editable": true,
"default": true
"default": false
},
{
"name": "id_can_adjust_locks",
@ -549,7 +549,7 @@
"label": "Connect",
"type": "checkbox",
"editable": true,
"default": true
"default": false
},
{
"name": "id_can_adjust_locks",
@ -620,7 +620,7 @@
"label": "Connect",
"type": "checkbox",
"editable": true,
"default": true
"default": false
},
{
"name": "id_can_adjust_locks",

View file

@ -140,7 +140,7 @@ NodePermissions DomainGatekeeper::applyPermissionsForUser(bool isLocalUser,
} else {
// they are logged into metaverse, but we don't have specific permissions for them.
userPerms |= _server->_settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn);
qDebug() << "user-permissions: user is logged-into metavers, so:" << userPerms;
qDebug() << "user-permissions: user is logged-into metaverse, so:" << userPerms;
// if this user is a friend of the domain-owner, give them friend's permissions
if (_domainOwnerFriends.contains(verifiedUsername)) {
@ -188,9 +188,9 @@ void DomainGatekeeper::updateNodePermissions() {
if (node->getPermissions().isAssignment) {
// this node is an assignment-client
userPerms.isAssignment = true;
userPerms.canAdjustLocks = true;
userPerms.canRezPermanentEntities = true;
userPerms.canRezTemporaryEntities = true;
userPerms.permissions |= NodePermissions::Permission::canAdjustLocks;
userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities;
userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities;
} else {
// this node is an agent
const QHostAddress& addr = node->getLocalSocket().getAddress();
@ -201,7 +201,7 @@ void DomainGatekeeper::updateNodePermissions() {
node->setPermissions(userPerms);
if (!userPerms.canConnectToDomain) {
if (!userPerms.can(NodePermissions::Permission::canConnectToDomain)) {
qDebug() << "node" << node->getUUID() << "no longer has permission to connect.";
// hang up on this node
nodesToKill << node;
@ -257,9 +257,9 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
// always allow assignment clients to create and destroy entities
NodePermissions userPerms;
userPerms.isAssignment = true;
userPerms.canAdjustLocks = true;
userPerms.canRezPermanentEntities = true;
userPerms.canRezTemporaryEntities = true;
userPerms.permissions |= NodePermissions::Permission::canAdjustLocks;
userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities;
userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities;
newNode->setPermissions(userPerms);
return newNode;
}
@ -306,13 +306,13 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
userPerms = applyPermissionsForUser(isLocalUser, userPerms, verifiedUsername);
if (!userPerms.canConnectToDomain) {
if (!userPerms.can(NodePermissions::Permission::canConnectToDomain)) {
sendConnectionDeniedPacket("You lack the required permissions to connect to this domain.",
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::TooManyUsers);
return SharedNodePointer();
}
if (!userPerms.canConnectPastMaxCapacity && !isWithinMaxCapacity()) {
if (!userPerms.can(NodePermissions::Permission::canConnectPastMaxCapacity) && !isWithinMaxCapacity()) {
// we can't allow this user to connect because we are at max capacity
sendConnectionDeniedPacket("Too many connected users.", nodeConnection.senderSockAddr,
DomainHandler::ConnectionRefusedReason::TooManyUsers);

View file

@ -184,10 +184,10 @@ void DomainMetadata::securityChanged(bool send) {
QString restriction;
const auto& settingsManager = static_cast<DomainServer*>(parent())->_settingsManager;
bool hasAnonymousAccess =
settingsManager.getStandardPermissionsForName(NodePermissions::standardNameAnonymous).canConnectToDomain;
bool hasHifiAccess =
settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn).canConnectToDomain;
bool hasAnonymousAccess = settingsManager.getStandardPermissionsForName(NodePermissions::standardNameAnonymous).can(
NodePermissions::Permission::canConnectToDomain);
bool hasHifiAccess = settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn).can(
NodePermissions::Permission::canConnectToDomain);
if (hasAnonymousAccess) {
restriction = hasHifiAccess ? RESTRICTION_OPEN : RESTRICTION_ANON;
} else if (hasHifiAccess) {

View file

@ -1099,7 +1099,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
// consider the domain to be "restricted" if anonymous connections are disallowed
static const QString RESTRICTED_ACCESS_FLAG = "restricted";
NodePermissions anonymousPermissions = _settingsManager.getPermissionsForName(NodePermissions::standardNameAnonymous);
domainObject[RESTRICTED_ACCESS_FLAG] = !anonymousPermissions.canConnectToDomain;
domainObject[RESTRICTED_ACCESS_FLAG] = !anonymousPermissions.can(NodePermissions::Permission::canConnectToDomain);
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
if (!temporaryDomainKey.isEmpty()) {

View file

@ -223,14 +223,16 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
if (isRestrictedAccess) {
// only users in allow-users list can connect
_standardAgentPermissions[NodePermissions::standardNameAnonymous]->canConnectToDomain = false;
_standardAgentPermissions[NodePermissions::standardNameLoggedIn]->canConnectToDomain = false;
_standardAgentPermissions[NodePermissions::standardNameAnonymous]->clear(
NodePermissions::Permission::canConnectToDomain);
_standardAgentPermissions[NodePermissions::standardNameLoggedIn]->clear(
NodePermissions::Permission::canConnectToDomain);
} // else anonymous and logged-in retain default of canConnectToDomain = true
foreach (QString allowedUser, allowedUsers) {
// even if isRestrictedAccess is false, we have to add explicit rows for these users.
// defaults to canConnectToDomain = true
_agentPermissions[allowedUser].reset(new NodePermissions(allowedUser));
_agentPermissions[allowedUser]->set(NodePermissions::Permission::canConnectToDomain);
}
foreach (QString allowedEditor, allowedEditors) {
@ -238,10 +240,10 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
_agentPermissions[allowedEditor].reset(new NodePermissions(allowedEditor));
if (isRestrictedAccess) {
// they can change locks, but can't connect.
_agentPermissions[allowedEditor]->canConnectToDomain = false;
_agentPermissions[allowedEditor]->clear(NodePermissions::Permission::canConnectToDomain);
}
}
_agentPermissions[allowedEditor]->canAdjustLocks = true;
_agentPermissions[allowedEditor]->set(NodePermissions::Permission::canAdjustLocks);
}
QList<QHash<QString, NodePermissionsPointer>> permissionsSets;
@ -249,11 +251,16 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
foreach (auto permissionsSet, permissionsSets) {
foreach (QString userName, permissionsSet.keys()) {
if (onlyEditorsAreRezzers) {
permissionsSet[userName]->canRezPermanentEntities = permissionsSet[userName]->canAdjustLocks;
permissionsSet[userName]->canRezTemporaryEntities = permissionsSet[userName]->canAdjustLocks;
if (permissionsSet[userName]->can(NodePermissions::Permission::canAdjustLocks)) {
permissionsSet[userName]->set(NodePermissions::Permission::canRezPermanentEntities);
permissionsSet[userName]->set(NodePermissions::Permission::canRezTemporaryEntities);
} else {
permissionsSet[userName]->clear(NodePermissions::Permission::canRezPermanentEntities);
permissionsSet[userName]->clear(NodePermissions::Permission::canRezTemporaryEntities);
}
} else {
permissionsSet[userName]->canRezPermanentEntities = true;
permissionsSet[userName]->canRezTemporaryEntities = true;
permissionsSet[userName]->set(NodePermissions::Permission::canRezPermanentEntities);
permissionsSet[userName]->set(NodePermissions::Permission::canRezTemporaryEntities);
}
}
}

View file

@ -135,17 +135,21 @@ void LimitedNodeList::setPermissions(const NodePermissions& newPermissions) {
_permissions = newPermissions;
if (originalPermissions.canAdjustLocks != newPermissions.canAdjustLocks) {
emit isAllowedEditorChanged(_permissions.canAdjustLocks);
if (originalPermissions.can(NodePermissions::Permission::canAdjustLocks) !=
newPermissions.can(NodePermissions::Permission::canAdjustLocks)) {
emit isAllowedEditorChanged(_permissions.can(NodePermissions::Permission::canAdjustLocks));
}
if (originalPermissions.canRezPermanentEntities != newPermissions.canRezPermanentEntities) {
emit canRezChanged(_permissions.canRezPermanentEntities);
if (originalPermissions.can(NodePermissions::Permission::canRezPermanentEntities) !=
newPermissions.can(NodePermissions::Permission::canRezPermanentEntities)) {
emit canRezChanged(_permissions.can(NodePermissions::Permission::canRezPermanentEntities));
}
if (originalPermissions.canRezTemporaryEntities != newPermissions.canRezTemporaryEntities) {
emit canRezTmpChanged(_permissions.canRezTemporaryEntities);
if (originalPermissions.can(NodePermissions::Permission::canRezTemporaryEntities) !=
newPermissions.can(NodePermissions::Permission::canRezTemporaryEntities)) {
emit canRezTmpChanged(_permissions.can(NodePermissions::Permission::canRezTemporaryEntities));
}
if (originalPermissions.canWriteToAssetServer != newPermissions.canWriteToAssetServer) {
emit canWriteAssetsChanged(_permissions.canWriteToAssetServer);
if (originalPermissions.can(NodePermissions::Permission::canWriteToAssetServer) !=
newPermissions.can(NodePermissions::Permission::canWriteToAssetServer)) {
emit canWriteAssetsChanged(_permissions.can(NodePermissions::Permission::canWriteToAssetServer));
}
}

View file

@ -105,10 +105,10 @@ public:
void setSessionUUID(const QUuid& sessionUUID);
void setPermissions(const NodePermissions& newPermissions);
bool isAllowedEditor() const { return _permissions.canAdjustLocks; }
bool getThisNodeCanRez() const { return _permissions.canRezPermanentEntities; }
bool getThisNodeCanRezTmp() const { return _permissions.canRezTemporaryEntities; }
bool getThisNodeCanWriteAssets() const { return _permissions.canWriteToAssetServer; }
bool isAllowedEditor() const { return _permissions.can(NodePermissions::Permission::canAdjustLocks); }
bool getThisNodeCanRez() const { return _permissions.can(NodePermissions::Permission::canRezPermanentEntities); }
bool getThisNodeCanRezTmp() const { return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); }
bool getThisNodeCanWriteAssets() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); }
quint16 getSocketLocalPort() const { return _nodeSocket.localPort(); }
QUdpSocket& getDTLSSocket();

View file

@ -61,10 +61,10 @@ public:
void setPermissions(const NodePermissions& newPermissions) { _permissions = newPermissions; }
NodePermissions getPermissions() const { return _permissions; }
bool isAllowedEditor() const { return _permissions.canAdjustLocks; }
bool getCanRez() const { return _permissions.canRezPermanentEntities; }
bool getCanRezTmp() const { return _permissions.canRezTemporaryEntities; }
bool getCanWriteToAssetServer() const { return _permissions.canWriteToAssetServer; }
bool isAllowedEditor() const { return _permissions.can(NodePermissions::Permission::canAdjustLocks); }
bool getCanRez() const { return _permissions.can(NodePermissions::Permission::canRezPermanentEntities); }
bool getCanRezTmp() const { return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); }
bool getCanWriteToAssetServer() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); }
friend QDataStream& operator<<(QDataStream& out, const Node& node);
friend QDataStream& operator>>(QDataStream& in, Node& node);

View file

@ -31,12 +31,14 @@ NodePermissions::NodePermissions(QMap<QString, QVariant> perms) {
_groupID = perms["group_id"].toUuid();
}
canConnectToDomain = perms["id_can_connect"].toBool();
canAdjustLocks = perms["id_can_adjust_locks"].toBool();
canRezPermanentEntities = perms["id_can_rez"].toBool();
canRezTemporaryEntities = perms["id_can_rez_tmp"].toBool();
canWriteToAssetServer = perms["id_can_write_to_asset_server"].toBool();
canConnectPastMaxCapacity = perms["id_can_connect_past_max_capacity"].toBool();
permissions = NodePermissions::Permissions();
permissions |= perms["id_can_connect"].toBool() ? Permission::canConnectToDomain : Permission::none;
permissions |= perms["id_can_adjust_locks"].toBool() ? Permission::canAdjustLocks : Permission::none;
permissions |= perms["id_can_rez"].toBool() ? Permission::canRezPermanentEntities : Permission::none;
permissions |= perms["id_can_rez_tmp"].toBool() ? Permission::canRezTemporaryEntities : Permission::none;
permissions |= perms["id_can_write_to_asset_server"].toBool() ? Permission::canWriteToAssetServer : Permission::none;
permissions |= perms["id_can_connect_past_max_capacity"].toBool() ?
Permission::canConnectPastMaxCapacity : Permission::none;
}
QVariant NodePermissions::toVariant() {
@ -45,31 +47,24 @@ QVariant NodePermissions::toVariant() {
if (_groupIDSet) {
values["group_id"] = _groupID;
}
values["id_can_connect"] = canConnectToDomain;
values["id_can_adjust_locks"] = canAdjustLocks;
values["id_can_rez"] = canRezPermanentEntities;
values["id_can_rez_tmp"] = canRezTemporaryEntities;
values["id_can_write_to_asset_server"] = canWriteToAssetServer;
values["id_can_connect_past_max_capacity"] = canConnectPastMaxCapacity;
values["id_can_connect"] = can(Permission::canConnectToDomain);
values["id_can_adjust_locks"] = can(Permission::canAdjustLocks);
values["id_can_rez"] = can(Permission::canRezPermanentEntities);
values["id_can_rez_tmp"] = can(Permission::canRezTemporaryEntities);
values["id_can_write_to_asset_server"] = can(Permission::canWriteToAssetServer);
values["id_can_connect_past_max_capacity"] = can(Permission::canConnectPastMaxCapacity);
return QVariant(values);
}
void NodePermissions::setAll(bool value) {
canConnectToDomain = value;
canAdjustLocks = value;
canRezPermanentEntities = value;
canRezTemporaryEntities = value;
canWriteToAssetServer = value;
canConnectPastMaxCapacity = value;
permissions = NodePermissions::Permissions();
if (value) {
permissions = ~permissions;
}
}
NodePermissions& NodePermissions::operator|=(const NodePermissions& rhs) {
this->canConnectToDomain |= rhs.canConnectToDomain;
this->canAdjustLocks |= rhs.canAdjustLocks;
this->canRezPermanentEntities |= rhs.canRezPermanentEntities;
this->canRezTemporaryEntities |= rhs.canRezTemporaryEntities;
this->canWriteToAssetServer |= rhs.canWriteToAssetServer;
this->canConnectPastMaxCapacity |= rhs.canConnectPastMaxCapacity;
permissions |= rhs.permissions;
return *this;
}
NodePermissions& NodePermissions::operator|=(const NodePermissionsPointer& rhs) {
@ -84,14 +79,15 @@ NodePermissionsPointer& operator|=(NodePermissionsPointer& lhs, const NodePermis
}
return lhs;
}
NodePermissionsPointer& operator|=(NodePermissionsPointer& lhs, NodePermissions::Permission rhs) {
if (lhs) {
lhs.get()->permissions |= rhs;
}
return lhs;
}
NodePermissions& NodePermissions::operator&=(const NodePermissions& rhs) {
this->canConnectToDomain &= rhs.canConnectToDomain;
this->canAdjustLocks &= rhs.canAdjustLocks;
this->canRezPermanentEntities &= rhs.canRezPermanentEntities;
this->canRezTemporaryEntities &= rhs.canRezTemporaryEntities;
this->canWriteToAssetServer &= rhs.canWriteToAssetServer;
this->canConnectPastMaxCapacity &= rhs.canConnectPastMaxCapacity;
permissions &= rhs.permissions;
return *this;
}
NodePermissions& NodePermissions::operator&=(const NodePermissionsPointer& rhs) {
@ -106,15 +102,16 @@ NodePermissionsPointer& operator&=(NodePermissionsPointer& lhs, const NodePermis
}
return lhs;
}
NodePermissionsPointer& operator&=(NodePermissionsPointer& lhs, NodePermissions::Permission rhs) {
if (lhs) {
lhs.get()->permissions &= rhs;
}
return lhs;
}
NodePermissions NodePermissions::operator~() {
NodePermissions result = *this;
result.canConnectToDomain = !result.canConnectToDomain;
result.canAdjustLocks = !result.canAdjustLocks;
result.canRezPermanentEntities = !result.canRezPermanentEntities;
result.canRezTemporaryEntities = !result.canRezTemporaryEntities;
result.canWriteToAssetServer = !result.canWriteToAssetServer;
result.canConnectPastMaxCapacity = !result.canConnectPastMaxCapacity;
result.permissions = ~permissions;
return result;
}
@ -128,43 +125,35 @@ NodePermissionsPointer operator~(NodePermissionsPointer& lhs) {
}
QDataStream& operator<<(QDataStream& out, const NodePermissions& perms) {
out << perms.canConnectToDomain;
out << perms.canAdjustLocks;
out << perms.canRezPermanentEntities;
out << perms.canRezTemporaryEntities;
out << perms.canWriteToAssetServer;
out << perms.canConnectPastMaxCapacity;
out << (uint)perms.permissions;
return out;
}
QDataStream& operator>>(QDataStream& in, NodePermissions& perms) {
in >> perms.canConnectToDomain;
in >> perms.canAdjustLocks;
in >> perms.canRezPermanentEntities;
in >> perms.canRezTemporaryEntities;
in >> perms.canWriteToAssetServer;
in >> perms.canConnectPastMaxCapacity;
uint permissionsInt;
in >> permissionsInt;
perms.permissions = (NodePermissions::Permissions)permissionsInt;
return in;
}
QDebug operator<<(QDebug debug, const NodePermissions& perms) {
debug.nospace() << "[permissions: " << perms.getID() << " --";
if (perms.canConnectToDomain) {
if (perms.can(NodePermissions::Permission::canConnectToDomain)) {
debug << " connect";
}
if (perms.canAdjustLocks) {
if (perms.can(NodePermissions::Permission::canAdjustLocks)) {
debug << " locks";
}
if (perms.canRezPermanentEntities) {
if (perms.can(NodePermissions::Permission::canRezPermanentEntities)) {
debug << " rez";
}
if (perms.canRezTemporaryEntities) {
if (perms.can(NodePermissions::Permission::canRezTemporaryEntities)) {
debug << " rez-tmp";
}
if (perms.canWriteToAssetServer) {
if (perms.can(NodePermissions::Permission::canWriteToAssetServer)) {
debug << " asset-server";
}
if (perms.canConnectPastMaxCapacity) {
if (perms.can(NodePermissions::Permission::canConnectPastMaxCapacity)) {
debug << " ignore-max-cap";
}
debug.nospace() << "]";

View file

@ -46,13 +46,17 @@ public:
static QString standardNameFriends;
static QStringList standardNames;
// the initializations here should match the defaults in describe-settings.json
bool canConnectToDomain { true };
bool canAdjustLocks { false };
bool canRezPermanentEntities { false };
bool canRezTemporaryEntities { false };
bool canWriteToAssetServer { false };
bool canConnectPastMaxCapacity { false };
enum class Permission {
none = 0,
canConnectToDomain = 1,
canAdjustLocks = 2,
canRezPermanentEntities = 4,
canRezTemporaryEntities = 8,
canWriteToAssetServer = 16,
canConnectPastMaxCapacity = 32
};
Q_DECLARE_FLAGS(Permissions, Permission)
Permissions permissions;
QVariant toVariant();
@ -66,6 +70,10 @@ public:
friend QDataStream& operator<<(QDataStream& out, const NodePermissions& perms);
friend QDataStream& operator>>(QDataStream& in, NodePermissions& perms);
void clear(Permission p) { permissions &= (Permission) (~(uint)p); }
void set(Permission p) { permissions |= p; }
bool can(Permission p) const { return permissions.testFlag(p); }
protected:
QString _id;
QString _userName;
@ -73,6 +81,7 @@ protected:
bool _groupIDSet { false };
QUuid _groupID;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(NodePermissions::Permissions)
// wrap QHash in a class that forces all keys to be lowercase
@ -96,7 +105,9 @@ const NodePermissions DEFAULT_AGENT_PERMISSIONS;
QDebug operator<<(QDebug debug, const NodePermissions& perms);
QDebug operator<<(QDebug debug, const NodePermissionsPointer& perms);
NodePermissionsPointer& operator|=(NodePermissionsPointer& lhs, const NodePermissionsPointer& rhs);
NodePermissionsPointer& operator|=(NodePermissionsPointer& lhs, NodePermissions::Permission rhs);
NodePermissionsPointer& operator&=(NodePermissionsPointer& lhs, const NodePermissionsPointer& rhs);
NodePermissionsPointer& operator&=(NodePermissionsPointer& lhs, NodePermissions::Permission rhs);
NodePermissionsPointer operator~(NodePermissionsPointer& lhs);
#endif // hifi_NodePermissions_h