diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json
index 44d2c025a7..885a289db4 100644
--- a/domain-server/resources/describe-settings.json
+++ b/domain-server/resources/describe-settings.json
@@ -526,7 +526,7 @@
"groups": [
{
"label": "Group",
- "span": 2
+ "span": 4
},
{
"label": "Permissions ?",
@@ -539,6 +539,14 @@
"name": "permissions_id",
"label": "Group Name"
},
+ {
+ "name": "rank",
+ "label": "Rank"
+ },
+ {
+ "name": "rank_name",
+ "label": "Rank Name"
+ },
{
"name": "group_id",
"label": "Group ID",
@@ -597,7 +605,7 @@
"groups": [
{
"label": "Group",
- "span": 2
+ "span": 4
},
{
"label": "Permissions ?",
@@ -610,6 +618,14 @@
"name": "permissions_id",
"label": "Group Name"
},
+ {
+ "name": "rank",
+ "label": "Rank"
+ },
+ {
+ "name": "rank_name",
+ "label": "Rank Name"
+ },
{
"name": "group_id",
"label": "Group ID",
diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp
index 77cd7ffb94..f85766105e 100644
--- a/domain-server/src/DomainGatekeeper.cpp
+++ b/domain-server/src/DomainGatekeeper.cpp
@@ -150,8 +150,9 @@ NodePermissions DomainGatekeeper::applyPermissionsForUser(bool isLocalUser,
// if this user is a known member of a group, give them the implied permissions
foreach (QUuid groupID, _server->_settingsManager.getGroupIDs()) {
- if (_server->_settingsManager.isGroupMember(verifiedUsername, groupID)) {
- userPerms |= _server->_settingsManager.getPermissionsForGroup(groupID);
+ int rank = _server->_settingsManager.isGroupMember(verifiedUsername, groupID);
+ if (rank >= 0) {
+ userPerms |= _server->_settingsManager.getPermissionsForGroup(groupID, rank);
qDebug() << "user-permissions: user is in group:" << groupID << "so:" << userPerms;
}
}
@@ -159,11 +160,13 @@ NodePermissions DomainGatekeeper::applyPermissionsForUser(bool isLocalUser,
// if this user is a known member of a blacklist group, remove the implied permissions
foreach (QUuid groupID, _server->_settingsManager.getBlacklistGroupIDs()) {
if (_server->_settingsManager.isGroupMember(verifiedUsername, groupID)) {
- userPerms &= ~_server->_settingsManager.getForbiddensForGroup(groupID);
- qDebug() << "user-permissions: user is in blacklist group:" << groupID << "so:" << userPerms;
+ int rank = _server->_settingsManager.isGroupMember(verifiedUsername, groupID);
+ if (rank >= 0) {
+ userPerms &= ~_server->_settingsManager.getForbiddensForGroup(groupID, rank);
+ qDebug() << "user-permissions: user is in blacklist group:" << groupID << "so:" << userPerms;
+ }
}
}
-
}
}
@@ -183,7 +186,7 @@ void DomainGatekeeper::updateNodePermissions() {
// the id and the username in NodePermissions will often be the same, but id is set before
// authentication and username is only set once they user's key has been confirmed.
QString username = node->getPermissions().getUserName();
- NodePermissions userPerms(username);
+ NodePermissions userPerms(NodePermissionsKey(username, 0));
if (node->getPermissions().isAssignment) {
// this node is an assignment-client
@@ -273,7 +276,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
auto limitedNodeList = DependencyManager::get();
// start with empty permissions
- NodePermissions userPerms(username);
+ NodePermissions userPerms(NodePermissionsKey(username, 0));
userPerms.setAll(false);
// check if this user is on our local machine - if this is true set permissions to those for a "localhost" connection
@@ -711,7 +714,7 @@ void DomainGatekeeper::getIsGroupMember(const QString& username, const QUuid gro
callbackParams.errorCallbackReceiver = this;
callbackParams.errorCallbackMethod = "getIsGroupMemberErrorCallback";
- const QString GET_IS_GROUP_MEMBER_PATH = "api/v1/groups/%1/membership/%2";
+ const QString GET_IS_GROUP_MEMBER_PATH = "api/v1/groups/%1/members/%2";
QString groupIDStr = groupID.toString().mid(1,36);
DependencyManager::get()->sendRequest(GET_IS_GROUP_MEMBER_PATH.arg(groupIDStr).arg(username),
AccountManagerAuth::Required,
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index fcbf4caa5b..d5bf8d9adc 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -112,7 +112,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
return;
}
- _settingsManager.requestMissingGroupIDs();
+ _settingsManager.apiRefreshGroupInformation();
setupNodeListAndAssignments();
setupAutomaticNetworking();
@@ -1097,7 +1097,6 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
static const QString AUTOMATIC_NETWORKING_KEY = "automatic_networking";
domainObject[AUTOMATIC_NETWORKING_KEY] = _automaticNetworkingSetting;
-
// add access level for anonymous connections
// consider the domain to be "restricted" if anonymous connections are disallowed
static const QString RESTRICTED_ACCESS_FLAG = "restricted";
diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp
index 5c27f37172..3f44b9a293 100644
--- a/domain-server/src/DomainServerSettingsManager.cpp
+++ b/domain-server/src/DomainServerSettingsManager.cpp
@@ -232,36 +232,37 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
foreach (QString allowedUser, allowedUsers) {
// even if isRestrictedAccess is false, we have to add explicit rows for these users.
- _agentPermissions[allowedUser].reset(new NodePermissions(allowedUser));
- _agentPermissions[allowedUser]->set(NodePermissions::Permission::canConnectToDomain);
+ _agentPermissions[NodePermissionsKey(allowedUser, 0)].reset(new NodePermissions(allowedUser));
+ _agentPermissions[NodePermissionsKey(allowedUser, 0)]->set(NodePermissions::Permission::canConnectToDomain);
}
foreach (QString allowedEditor, allowedEditors) {
- if (!_agentPermissions.contains(allowedEditor)) {
- _agentPermissions[allowedEditor].reset(new NodePermissions(allowedEditor));
+ NodePermissionsKey editorKey(allowedEditor, 0);
+ if (!_agentPermissions.contains(editorKey)) {
+ _agentPermissions[editorKey].reset(new NodePermissions(allowedEditor));
if (isRestrictedAccess) {
// they can change locks, but can't connect.
- _agentPermissions[allowedEditor]->clear(NodePermissions::Permission::canConnectToDomain);
+ _agentPermissions[editorKey]->clear(NodePermissions::Permission::canConnectToDomain);
}
}
- _agentPermissions[allowedEditor]->set(NodePermissions::Permission::canAdjustLocks);
+ _agentPermissions[editorKey]->set(NodePermissions::Permission::canAdjustLocks);
}
- QList> permissionsSets;
+ QList> permissionsSets;
permissionsSets << _standardAgentPermissions.get() << _agentPermissions.get();
foreach (auto permissionsSet, permissionsSets) {
- foreach (QString userName, permissionsSet.keys()) {
+ foreach (NodePermissionsKey userKey, permissionsSet.keys()) {
if (onlyEditorsAreRezzers) {
- if (permissionsSet[userName]->can(NodePermissions::Permission::canAdjustLocks)) {
- permissionsSet[userName]->set(NodePermissions::Permission::canRezPermanentEntities);
- permissionsSet[userName]->set(NodePermissions::Permission::canRezTemporaryEntities);
+ if (permissionsSet[userKey]->can(NodePermissions::Permission::canAdjustLocks)) {
+ permissionsSet[userKey]->set(NodePermissions::Permission::canRezPermanentEntities);
+ permissionsSet[userKey]->set(NodePermissions::Permission::canRezTemporaryEntities);
} else {
- permissionsSet[userName]->clear(NodePermissions::Permission::canRezPermanentEntities);
- permissionsSet[userName]->clear(NodePermissions::Permission::canRezTemporaryEntities);
+ permissionsSet[userKey]->clear(NodePermissions::Permission::canRezPermanentEntities);
+ permissionsSet[userKey]->clear(NodePermissions::Permission::canRezTemporaryEntities);
}
} else {
- permissionsSet[userName]->set(NodePermissions::Permission::canRezPermanentEntities);
- permissionsSet[userName]->set(NodePermissions::Permission::canRezTemporaryEntities);
+ permissionsSet[userKey]->set(NodePermissions::Permission::canRezPermanentEntities);
+ permissionsSet[userKey]->set(NodePermissions::Permission::canRezTemporaryEntities);
}
}
}
@@ -343,11 +344,17 @@ void DomainServerSettingsManager::packPermissionsForMap(QString mapName,
(*permissions) = QVariantList();
}
- // convert details for each member of the section
+ // convert details for each member of the subsection
QVariantList* permissionsList = reinterpret_cast(permissions);
(*permissionsList).clear();
- foreach (QString userName, agentPermissions.keys()) {
- *permissionsList += agentPermissions[userName]->toVariant();
+ foreach (NodePermissionsKey userKey, agentPermissions.keys()) {
+ NodePermissionsPointer perms = agentPermissions[userKey];
+ if (perms->isGroup()) {
+ QVector rankNames = _groupRanks[perms->getGroupID()];
+ *permissionsList += perms->toVariant(rankNames);
+ } else {
+ *permissionsList += perms->toVariant();
+ }
}
}
@@ -413,16 +420,17 @@ void DomainServerSettingsManager::unpackPermissions() {
foreach (QVariant permsHash, standardPermissionsList) {
NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) };
QString id = perms->getID();
- foundLocalhost |= (id == NodePermissions::standardNameLocalhost);
- foundAnonymous |= (id == NodePermissions::standardNameAnonymous);
- foundLoggedIn |= (id == NodePermissions::standardNameLoggedIn);
- foundFriends |= (id == NodePermissions::standardNameFriends);
- if (_standardAgentPermissions.contains(id)) {
+ NodePermissionsKey idKey = NodePermissionsKey(id, 0);
+ foundLocalhost |= (idKey == NodePermissions::standardNameLocalhost);
+ foundAnonymous |= (idKey == NodePermissions::standardNameAnonymous);
+ foundLoggedIn |= (idKey == NodePermissions::standardNameLoggedIn);
+ foundFriends |= (idKey == NodePermissions::standardNameFriends);
+ if (_standardAgentPermissions.contains(idKey)) {
qDebug() << "duplicate name in standard permissions table: " << id;
- _standardAgentPermissions[id] |= perms;
+ _standardAgentPermissions[idKey] |= perms;
needPack = true;
} else {
- _standardAgentPermissions[id] = perms;
+ _standardAgentPermissions[idKey] = perms;
}
}
@@ -430,12 +438,13 @@ void DomainServerSettingsManager::unpackPermissions() {
foreach (QVariant permsHash, permissionsList) {
NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) };
QString id = perms->getID();
- if (_agentPermissions.contains(id)) {
+ NodePermissionsKey idKey = NodePermissionsKey(id, 0);
+ if (_agentPermissions.contains(idKey)) {
qDebug() << "duplicate name in permissions table: " << id;
- _agentPermissions[id] |= perms;
+ _agentPermissions[idKey] |= perms;
needPack = true;
} else {
- _agentPermissions[id] = perms;
+ _agentPermissions[idKey] = perms;
}
}
@@ -443,16 +452,18 @@ void DomainServerSettingsManager::unpackPermissions() {
foreach (QVariant permsHash, groupPermissionsList) {
NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) };
QString id = perms->getID();
- if (_groupPermissions.contains(id)) {
+ NodePermissionsKey idKey = perms->getKey();
+ if (_groupPermissions.contains(idKey)) {
qDebug() << "duplicate name in group permissions table: " << id;
- _groupPermissions[id] |= perms;
+ _groupPermissions[idKey] |= perms;
needPack = true;
} else {
- _groupPermissions[id] = perms;
+ _groupPermissions[idKey] = perms;
}
if (perms->isGroup()) {
- // the group-id was cached. hook-up the id in the id->group hash
- _groupByID[perms->getGroupID()] = _groupPermissions[id];
+ // the group-id was cached. hook-up the uuid in the uuid->group hash
+ _groupPermissionsByUUID[GroupByUUIDKey(perms->getGroupID(), perms->getRank())] = _groupPermissions[idKey];
+ needPack |= setGroupID(perms->getID(), perms->getGroupID());
}
}
@@ -460,16 +471,18 @@ void DomainServerSettingsManager::unpackPermissions() {
foreach (QVariant permsHash, groupForbiddensList) {
NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) };
QString id = perms->getID();
- if (_groupForbiddens.contains(id)) {
+ NodePermissionsKey idKey = perms->getKey();
+ if (_groupForbiddens.contains(idKey)) {
qDebug() << "duplicate name in group forbiddens table: " << id;
- _groupForbiddens[id] |= perms;
+ _groupForbiddens[idKey] |= perms;
needPack = true;
} else {
- _groupForbiddens[id] = perms;
+ _groupForbiddens[idKey] = perms;
}
if (perms->isGroup()) {
- // the group-id was cached. hook-up the id in the id->group hash
- _groupByID[perms->getGroupID()] = _groupForbiddens[id];
+ // the group-id was cached. hook-up the uuid in the uuid->group hash
+ _groupForbiddensByUUID[GroupByUUIDKey(perms->getGroupID(), perms->getRank())] = _groupPermissions[idKey];
+ needPack |= setGroupID(perms->getID(), perms->getGroupID());
}
}
@@ -477,40 +490,42 @@ void DomainServerSettingsManager::unpackPermissions() {
if (!foundLocalhost) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameLocalhost) };
perms->setAll(true);
- _standardAgentPermissions[perms->getID()] = perms;
+ _standardAgentPermissions[perms->getKey()] = perms;
needPack = true;
}
if (!foundAnonymous) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameAnonymous) };
- _standardAgentPermissions[perms->getID()] = perms;
+ _standardAgentPermissions[perms->getKey()] = perms;
needPack = true;
}
if (!foundLoggedIn) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameLoggedIn) };
- _standardAgentPermissions[perms->getID()] = perms;
+ _standardAgentPermissions[perms->getKey()] = perms;
needPack = true;
}
if (!foundFriends) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameFriends) };
- _standardAgentPermissions[perms->getID()] = perms;
+ _standardAgentPermissions[perms->getKey()] = perms;
needPack = true;
}
+ needPack |= ensurePermissionsForGroupRanks();
+
if (needPack) {
packPermissions();
}
- // attempt to retrieve any missing group-IDs
- requestMissingGroupIDs();
+ // attempt to retrieve any missing group-IDs, etc
+ apiRefreshGroupInformation();
#ifdef WANT_DEBUG
qDebug() << "--------------- permissions ---------------------";
- QList> permissionsSets;
+ QList> permissionsSets;
permissionsSets << _standardAgentPermissions.get() << _agentPermissions.get()
<< _groupPermissions.get() << _groupForbiddens.get();
foreach (auto permissionSet, permissionsSets) {
- QHashIterator i(permissionSet);
+ QHashIterator i(permissionSet);
while (i.hasNext()) {
i.next();
NodePermissionsPointer perms = i.value();
@@ -524,7 +539,63 @@ void DomainServerSettingsManager::unpackPermissions() {
#endif
}
-NodePermissions DomainServerSettingsManager::getStandardPermissionsForName(const QString& name) const {
+bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() {
+ // make sure each rank in each group has its own set of permissions
+ bool changed = false;
+ QList permissionGroupIDs = getGroupIDs();
+ foreach (QUuid groupID, permissionGroupIDs) {
+ QString groupName = _groupNames[groupID];
+ int rankCountForGroup = _groupRanks[groupID].size();
+ for (int rank = 0; rank < rankCountForGroup; rank++) {
+ NodePermissionsKey nameKey = NodePermissionsKey(groupName, rank);
+ GroupByUUIDKey idKey = GroupByUUIDKey(groupID, rank);
+ NodePermissionsPointer perms;
+ if (_groupPermissions.contains(nameKey)) {
+ perms = _groupPermissions[nameKey];
+ } else {
+ perms = NodePermissionsPointer(new NodePermissions(nameKey));
+ perms->setGroupID(groupID);
+ _groupPermissions[nameKey] = perms;
+ changed = true;
+ }
+ _groupPermissionsByUUID[idKey] = perms;
+ }
+ }
+
+ QList forbiddenGroupIDs = getBlacklistGroupIDs();
+ foreach (QUuid groupID, forbiddenGroupIDs) {
+ QString groupName = _groupNames[groupID];
+ int rankCountForGroup = _groupRanks[groupID].size();
+ for (int rank = 0; rank < rankCountForGroup; rank++) {
+ NodePermissionsKey nameKey = NodePermissionsKey(groupName, rank);
+ GroupByUUIDKey idKey = GroupByUUIDKey(groupID, rank);
+ NodePermissionsPointer perms;
+ if (_groupForbiddens.contains(nameKey)) {
+ perms = _groupForbiddens[nameKey];
+ } else {
+ perms = NodePermissionsPointer(new NodePermissions(nameKey));
+ perms->setGroupID(groupID);
+ _groupForbiddens[nameKey] = perms;
+ changed = true;
+ }
+ _groupForbiddensByUUID[idKey] = perms;
+ }
+ }
+
+ debugDumpGroupsState();
+
+ return changed;
+}
+
+QStringList DomainServerSettingsManager::getAllNames() const {
+ QStringList result;
+ foreach (auto key, _agentPermissions.keys()) {
+ result << key.first.toLower();
+ }
+ return result;
+}
+
+NodePermissions DomainServerSettingsManager::getStandardPermissionsForName(const NodePermissionsKey& name) const {
if (_standardAgentPermissions.contains(name)) {
return *(_standardAgentPermissions[name].get());
}
@@ -534,55 +605,60 @@ NodePermissions DomainServerSettingsManager::getStandardPermissionsForName(const
}
NodePermissions DomainServerSettingsManager::getPermissionsForName(const QString& name) const {
- if (_agentPermissions.contains(name)) {
- return *(_agentPermissions[name].get());
+ NodePermissionsKey nameKey = NodePermissionsKey(name, 0);
+ if (_agentPermissions.contains(nameKey)) {
+ return *(_agentPermissions[nameKey].get());
}
NodePermissions nullPermissions;
nullPermissions.setAll(false);
return nullPermissions;
}
-NodePermissions DomainServerSettingsManager::getPermissionsForGroup(const QString& groupname) const {
- if (_groupPermissions.contains(groupname)) {
- return *(_groupPermissions[groupname].get());
+NodePermissions DomainServerSettingsManager::getPermissionsForGroup(const QString& groupName, int rank) const {
+ NodePermissionsKey groupRankKey = NodePermissionsKey(groupName, rank);
+ if (_groupPermissions.contains(groupRankKey)) {
+ return *(_groupPermissions[groupRankKey].get());
}
NodePermissions nullPermissions;
nullPermissions.setAll(false);
return nullPermissions;
}
-NodePermissions DomainServerSettingsManager::getPermissionsForGroup(const QUuid& groupID) const {
- if (!_groupByID.contains(groupID)) {
+NodePermissions DomainServerSettingsManager::getPermissionsForGroup(const QUuid& groupID, int rank) const {
+ GroupByUUIDKey byUUIDKey = GroupByUUIDKey(groupID, rank);
+ if (!_groupPermissionsByUUID.contains(byUUIDKey)) {
NodePermissions nullPermissions;
nullPermissions.setAll(false);
return nullPermissions;
}
- QString groupName = _groupByID[groupID]->getID();
- return getPermissionsForGroup(groupName);
+ NodePermissionsKey groupKey = _groupPermissionsByUUID[byUUIDKey]->getKey();
+ return getPermissionsForGroup(groupKey.first, groupKey.second);
}
-
-NodePermissions DomainServerSettingsManager::getForbiddensForGroup(const QString& groupname) const {
- if (_groupForbiddens.contains(groupname)) {
- return *(_groupForbiddens[groupname].get());
+NodePermissions DomainServerSettingsManager::getForbiddensForGroup(const QString& groupName, int rank) const {
+ NodePermissionsKey groupRankKey = NodePermissionsKey(groupName, rank);
+ if (_groupForbiddens.contains(groupRankKey)) {
+ return *(_groupForbiddens[groupRankKey].get());
}
NodePermissions nullForbiddens;
+ // XXX should this be setAll(true) ?
nullForbiddens.setAll(false);
return nullForbiddens;
}
-NodePermissions DomainServerSettingsManager::getForbiddensForGroup(const QUuid& groupID) const {
- if (!_groupByID.contains(groupID)) {
+NodePermissions DomainServerSettingsManager::getForbiddensForGroup(const QUuid& groupID, int rank) const {
+ GroupByUUIDKey byUUIDKey = GroupByUUIDKey(groupID, rank);
+ if (!_groupForbiddensByUUID.contains(byUUIDKey)) {
NodePermissions nullForbiddens;
+ // XXX should this be setAll(true) ?
nullForbiddens.setAll(false);
return nullForbiddens;
}
- QString groupName = _groupByID[groupID]->getID();
- return getForbiddensForGroup(groupName);
+
+ NodePermissionsKey groupKey = _groupForbiddensByUUID[byUUIDKey]->getKey();
+ return getForbiddensForGroup(groupKey.first, groupKey.second);
}
-
-
QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QString& keyPath) {
const QVariant* foundValue = valueForKeyPath(_configMap.getMergedConfig(), keyPath);
@@ -854,7 +930,8 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
sortPermissions();
}
-QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJsonObject& groupObject, const QString& settingName) {
+QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJsonObject& groupObject,
+ const QString& settingName) {
foreach(const QJsonValue& settingValue, groupObject[DESCRIPTION_SETTINGS_KEY].toArray()) {
QJsonObject settingObject = settingValue.toObject();
if (settingObject[DESCRIPTION_NAME_KEY].toString() == settingName) {
@@ -967,6 +1044,12 @@ bool permissionVariantLessThan(const QVariant &v1, const QVariant &v2) {
!m2.contains("permissions_id")) {
return v1.toString() < v2.toString();
}
+
+ if (m1.contains("rank_name") && m2.contains("rank_name") &&
+ m1["permissions_id"].toString() == m2["permissions_id"].toString()) {
+ return m1["rank_name"].toString() < m2["rank_name"].toString();
+ }
+
return m1["permissions_id"].toString() < m2["permissions_id"].toString();
}
@@ -1003,62 +1086,94 @@ void DomainServerSettingsManager::persistToFile() {
}
}
-void DomainServerSettingsManager::requestMissingGroupIDs() {
+QStringList DomainServerSettingsManager::getAllKnownGroupNames() {
+ // extract all the group names from the group-permissions and group-forbiddens settings
+ QSet result;
+
+ QHashIterator i_permissions(_groupPermissions.get());
+ while (i_permissions.hasNext()) {
+ i_permissions.next();
+ NodePermissionsKey key = i_permissions.key();
+ result += key.first;
+ }
+
+ QHashIterator i_forbiddens(_groupForbiddens.get());
+ while (i_forbiddens.hasNext()) {
+ i_forbiddens.next();
+ NodePermissionsKey key = i_forbiddens.key();
+ result += key.first;
+ }
+
+ return result.toList();
+}
+
+bool DomainServerSettingsManager::setGroupID(const QString& groupName, const QUuid& groupID) {
+ bool changed = false;
+ _groupIDs[groupName.toLower()] = groupID;
+ _groupNames[groupID] = groupName;
+
+ QHashIterator i_permissions(_groupPermissions.get());
+ while (i_permissions.hasNext()) {
+ i_permissions.next();
+ NodePermissionsPointer perms = i_permissions.value();
+ if (perms->getID().toLower() == groupName.toLower() && !perms->isGroup()) {
+ changed = true;
+ perms->setGroupID(groupID);
+ }
+ }
+
+ QHashIterator i_forbiddens(_groupForbiddens.get());
+ while (i_forbiddens.hasNext()) {
+ i_forbiddens.next();
+ NodePermissionsPointer perms = i_forbiddens.value();
+ if (perms->getID().toLower() == groupName.toLower() && !perms->isGroup()) {
+ changed = true;
+ perms->setGroupID(groupID);
+ }
+ }
+
+ return changed;
+}
+
+void DomainServerSettingsManager::apiRefreshGroupInformation() {
+ const int STALE_DATA_AGE = 600; // seconds
+
if (!DependencyManager::get()->hasAuthEndpoint()) {
// can't yet.
return;
}
- QHashIterator i_permissions(_groupPermissions.get());
- while (i_permissions.hasNext()) {
- i_permissions.next();
- NodePermissionsPointer perms = i_permissions.value();
- if (!perms->getGroupID().isNull()) {
- // we already know this group's ID
+ QStringList groupNames = getAllKnownGroupNames();
+ foreach (QString groupName, groupNames) {
+ if (_groupIDs.contains(groupName.toLower())) {
+ // we already know about this one
continue;
}
-
- // make a call to metaverse api to turn the group name into a group ID
- getGroupID(perms->getID());
+ apiGetGroupID(groupName);
}
- QHashIterator i_forbiddens(_groupForbiddens.get());
- while (i_forbiddens.hasNext()) {
- i_forbiddens.next();
- NodePermissionsPointer perms = i_forbiddens.value();
- if (!perms->getGroupID().isNull()) {
- // we already know this group's ID
- continue;
- }
- // make a call to metaverse api to turn the group name into a group ID
- getGroupID(perms->getID());
+ quint64 now = usecTimestampNow();
+ foreach (QUuid groupID, _groupNames.keys()) {
+ if (now - _groupRanksLastFetched[groupID] > STALE_DATA_AGE * USECS_PER_SECOND) {
+ apiGetGroupRanks(groupID);
+ }
}
}
-NodePermissionsPointer DomainServerSettingsManager::lookupGroupByID(const QUuid& id) {
- if (_groupByID.contains(id)) {
- return _groupByID[id];
- }
- return nullptr;
-}
-
-void DomainServerSettingsManager::getGroupID(const QString& groupname) {
+void DomainServerSettingsManager::apiGetGroupID(const QString& groupName) {
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
- callbackParams.jsonCallbackMethod = "getGroupIDJSONCallback";
+ callbackParams.jsonCallbackMethod = "apiGetGroupIDJSONCallback";
callbackParams.errorCallbackReceiver = this;
- callbackParams.errorCallbackMethod = "getGroupIDErrorCallback";
+ callbackParams.errorCallbackMethod = "apiGetGroupIDErrorCallback";
- const QString GET_GROUP_ID_PATH = "api/v1/groups/name/%1";
-
- qDebug() << "************* Requesting group ID for group named" << groupname;
-
- DependencyManager::get()->sendRequest(GET_GROUP_ID_PATH.arg(groupname),
+ const QString GET_GROUP_ID_PATH = "api/v1/groups/names/%1";
+ DependencyManager::get()->sendRequest(GET_GROUP_ID_PATH.arg(groupName),
AccountManagerAuth::Required,
QNetworkAccessManager::GetOperation, callbackParams);
}
-void DomainServerSettingsManager::getGroupIDJSONCallback(QNetworkReply& requestReply) {
+void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& requestReply) {
// {
// "data":{
// "groups":[{
@@ -1090,7 +1205,6 @@ void DomainServerSettingsManager::getGroupIDJSONCallback(QNetworkReply& requestR
// "status":"success"
// }
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
-
if (jsonObject["status"].toString() == "success") {
QJsonArray groups = jsonObject["data"].toObject()["groups"].toArray();
for (int i = 0; i < groups.size(); i++) {
@@ -1098,25 +1212,10 @@ void DomainServerSettingsManager::getGroupIDJSONCallback(QNetworkReply& requestR
QString groupName = group["name"].toString();
QUuid groupID = QUuid(group["id"].toString());
- bool found = false;
- if (_groupPermissions.contains(groupName)) {
- qDebug() << "ID for group:" << groupName << "is" << groupID;
- _groupPermissions[groupName]->setGroupID(groupID);
- _groupByID[groupID] = _groupPermissions[groupName];
- found = true;
- }
- if (_groupForbiddens.contains(groupName)) {
- qDebug() << "ID for group:" << groupName << "is" << groupID;
- _groupForbiddens[groupName]->setGroupID(groupID);
- _groupByID[groupID] = _groupForbiddens[groupName];
- found = true;
- }
-
- if (found) {
+ bool changed = setGroupID(groupName, groupID);
+ if (changed) {
packPermissions();
- getGroupRanks(groupID);
- } else {
- qDebug() << "DomainServerSettingsManager::getGroupIDJSONCallback got response for unknown group:" << groupName;
+ apiGetGroupRanks(groupID);
}
}
} else {
@@ -1124,27 +1223,26 @@ void DomainServerSettingsManager::getGroupIDJSONCallback(QNetworkReply& requestR
}
}
-void DomainServerSettingsManager::getGroupIDErrorCallback(QNetworkReply& requestReply) {
+void DomainServerSettingsManager::apiGetGroupIDErrorCallback(QNetworkReply& requestReply) {
qDebug() << "******************** getGroupID api call failed:" << requestReply.error();
}
-void DomainServerSettingsManager::getGroupRanks(const QUuid& groupID) {
+void DomainServerSettingsManager::apiGetGroupRanks(const QUuid& groupID) {
+ _groupRanksLastFetched[groupID] = usecTimestampNow();
+
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
- callbackParams.jsonCallbackMethod = "getGroupRanksJSONCallback";
+ callbackParams.jsonCallbackMethod = "apiGetGroupRanksJSONCallback";
callbackParams.errorCallbackReceiver = this;
- callbackParams.errorCallbackMethod = "getGroupRanksErrorCallback";
+ callbackParams.errorCallbackMethod = "apiGetGroupRanksErrorCallback";
const QString GET_GROUP_RANKS_PATH = "api/v1/groups/%1/ranks";
-
- qDebug() << "************* Requesting group ranks for group" << groupID;
-
DependencyManager::get()->sendRequest(GET_GROUP_RANKS_PATH.arg(groupID.toString().mid(1,36)),
AccountManagerAuth::Required,
QNetworkAccessManager::GetOperation, callbackParams);
}
-void DomainServerSettingsManager::getGroupRanksJSONCallback(QNetworkReply& requestReply) {
+void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& requestReply) {
// {
// "current_page":1,
// "data":{
@@ -1195,6 +1293,7 @@ void DomainServerSettingsManager::getGroupRanksJSONCallback(QNetworkReply& reque
// "total_pages":1
// }
+ bool changed = false;
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
if (jsonObject["status"].toString() == "success") {
QJsonObject groups = jsonObject["data"].toObject()["groups"].toObject();
@@ -1205,47 +1304,97 @@ void DomainServerSettingsManager::getGroupRanksJSONCallback(QNetworkReply& reque
QJsonObject rank = ranks.at(rankIndex).toObject();
QString rankName = rank["name"].toString();
int rankOrder = rank["order"].toInt();
- qDebug() << "**** " << groupID << "rank name =" << rankName << " order =" << rankOrder;
QVector& ranksForGroup = _groupRanks[groupID];
if (ranksForGroup.size() < rankOrder + 1) {
ranksForGroup.resize(rankOrder + 1);
+ changed = true;
+ }
+ if (ranksForGroup[rankOrder] != rankName) {
+ ranksForGroup[rankOrder] = rankName;
+ changed = true;
}
- ranksForGroup[rankOrder] = rankName;
}
}
+
+ changed |= ensurePermissionsForGroupRanks();
+ if (changed) {
+ packPermissions();
+ }
} else {
qDebug() << "getGroupRanks api call returned:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
}
}
-void DomainServerSettingsManager::getGroupRanksErrorCallback(QNetworkReply& requestReply) {
+void DomainServerSettingsManager::apiGetGroupRanksErrorCallback(QNetworkReply& requestReply) {
qDebug() << "******************** getGroupRanks api call failed:" << requestReply.error();
}
-void DomainServerSettingsManager::recordGroupMembership(const QString& name, const QUuid groupID, bool isMember) {
- _groupMembership[name][groupID] = isMember;
+void DomainServerSettingsManager::recordGroupMembership(const QString& name, const QUuid groupID, int rank) {
+ if (rank >= 0) {
+ _groupMembership[name][groupID] = rank;
+ } else {
+ _groupMembership[name].remove(groupID);
+ }
}
-bool DomainServerSettingsManager::isGroupMember(const QString& name, const QUuid& groupID) {
- return _groupMembership[name][groupID];
+int DomainServerSettingsManager::isGroupMember(const QString& name, const QUuid& groupID) {
+ const QHash& groupsForName = _groupMembership[name];
+ if (groupsForName.contains(groupID)) {
+ return groupsForName[groupID];
+ }
+ return -1;
}
QList DomainServerSettingsManager::getGroupIDs() {
- QList result;
- foreach (QString groupName, _groupPermissions.keys()) {
- if (_groupPermissions[groupName]->isGroup()) {
- result << _groupPermissions[groupName]->getGroupID();
+ QSet result;
+ foreach (NodePermissionsKey groupKey, _groupPermissions.keys()) {
+ if (_groupPermissions[groupKey]->isGroup()) {
+ result += _groupPermissions[groupKey]->getGroupID();
}
}
- return result;
+ return result.toList();
}
QList DomainServerSettingsManager::getBlacklistGroupIDs() {
- QList result;
- foreach (QString groupName, _groupForbiddens.keys()) {
- if (_groupForbiddens[groupName]->isGroup()) {
- result << _groupForbiddens[groupName]->getGroupID();
+ QSet result;
+ foreach (NodePermissionsKey groupKey, _groupForbiddens.keys()) {
+ if (_groupForbiddens[groupKey]->isGroup()) {
+ result += _groupForbiddens[groupKey]->getGroupID();
}
}
- return result;
+ return result.toList();
+}
+
+void DomainServerSettingsManager::debugDumpGroupsState() {
+ qDebug() << "--------- GROUPS ---------";
+
+ qDebug() << "_groupPermissions:";
+ foreach (NodePermissionsKey groupKey, _groupPermissions.keys()) {
+ NodePermissionsPointer perms = _groupPermissions[groupKey];
+ qDebug() << "| " << groupKey << perms;
+ }
+
+ qDebug() << "_groupIDs:";
+ foreach (QString groupName, _groupIDs.keys()) {
+ qDebug() << "| " << groupName << "==>" << _groupIDs[groupName];
+ }
+
+ qDebug() << "_groupNames:";
+ foreach (QUuid groupID, _groupNames.keys()) {
+ qDebug() << "| " << groupID << "==>" << _groupNames[groupID];
+ }
+
+ qDebug() << "_groupRanks:";
+ foreach (QUuid groupID, _groupRanks.keys()) {
+ QVector& ranksForGroup = _groupRanks[groupID];
+ QString readableRanks;
+ foreach (QString rankName, ranksForGroup) {
+ if (readableRanks == "") {
+ readableRanks = rankName;
+ } else {
+ readableRanks += "," + rankName;
+ }
+ }
+ qDebug() << "| " << groupID << "==>" << readableRanks;
+ }
}
diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h
index 706717eda8..52e4b02e26 100644
--- a/domain-server/src/DomainServerSettingsManager.h
+++ b/domain-server/src/DomainServerSettingsManager.h
@@ -30,6 +30,8 @@ const QString AGENT_PERMISSIONS_KEYPATH = "security.permissions";
const QString GROUP_PERMISSIONS_KEYPATH = "security.group_permissions";
const QString GROUP_FORBIDDENS_KEYPATH = "security.group_forbiddens";
+using GroupByUUIDKey = QPair;
+
class DomainServerSettingsManager : public QObject {
Q_OBJECT
public:
@@ -46,40 +48,46 @@ public:
QVariantMap& getDescriptorsMap();
// these give access to anonymous/localhost/logged-in settings from the domain-server settings page
- bool haveStandardPermissionsForName(const QString& name) const { return _standardAgentPermissions.contains(name); }
- NodePermissions getStandardPermissionsForName(const QString& name) const;
+ bool haveStandardPermissionsForName(const QString& name) const { return _standardAgentPermissions.contains(name, 0); }
+ NodePermissions getStandardPermissionsForName(const NodePermissionsKey& name) const;
// these give access to permissions for specific user-names from the domain-server settings page
- bool havePermissionsForName(const QString& name) const { return _agentPermissions.contains(name); }
+ bool havePermissionsForName(const QString& name) const { return _agentPermissions.contains(name, 0); }
NodePermissions getPermissionsForName(const QString& name) const;
- QStringList getAllNames() { return _agentPermissions.keys(); }
+ NodePermissions getPermissionsForName(const NodePermissionsKey& key) const { return getPermissionsForName(key.first); }
+ QStringList getAllNames() const;
// these give access to permissions for specific groups from the domain-server settings page
- bool havePermissionsForGroup(const QString& groupname) const { return _groupPermissions.contains(groupname); }
- NodePermissions getPermissionsForGroup(const QString& groupname) const;
- NodePermissions getPermissionsForGroup(const QUuid& groupID) const;
+ bool havePermissionsForGroup(const QString& groupName, int rank) const {
+ return _groupPermissions.contains(groupName, rank);
+ }
+ NodePermissions getPermissionsForGroup(const QString& groupName, int rank) const;
+ NodePermissions getPermissionsForGroup(const QUuid& groupID, int rank) const;
// these remove permissions from users in certain groups
- bool haveForbiddensForGroup(const QString& groupname) const { return _groupForbiddens.contains(groupname); }
- NodePermissions getForbiddensForGroup(const QString& groupname) const;
- NodePermissions getForbiddensForGroup(const QUuid& groupID) const;
+ bool haveForbiddensForGroup(const QString& groupName, int rank) const { return _groupForbiddens.contains(groupName, rank); }
+ NodePermissions getForbiddensForGroup(const QString& groupName, int rank) const;
+ NodePermissions getForbiddensForGroup(const QUuid& groupID, int rank) const;
+
+ QStringList getAllKnownGroupNames();
+ bool setGroupID(const QString& groupName, const QUuid& groupID);
QList getGroupIDs();
QList getBlacklistGroupIDs();
// these are used to locally cache the result of calling "api/v1/groups/.../is_member/..." on metaverse's api
void clearGroupMemberships(const QString& name) { _groupMembership[name].clear(); }
- void recordGroupMembership(const QString& name, const QUuid groupID, bool isMember);
- bool isGroupMember(const QString& name, const QUuid& groupID);
+ void recordGroupMembership(const QString& name, const QUuid groupID, int rank);
+ int isGroupMember(const QString& name, const QUuid& groupID); // returns rank or -1 if not a member
signals:
void updateNodePermissions();
public slots:
- void getGroupIDJSONCallback(QNetworkReply& requestReply);
- void getGroupIDErrorCallback(QNetworkReply& requestReply);
- void getGroupRanksJSONCallback(QNetworkReply& requestReply);
- void getGroupRanksErrorCallback(QNetworkReply& requestReply);
+ void apiGetGroupIDJSONCallback(QNetworkReply& requestReply);
+ void apiGetGroupIDErrorCallback(QNetworkReply& requestReply);
+ void apiGetGroupRanksJSONCallback(QNetworkReply& requestReply);
+ void apiGetGroupRanksErrorCallback(QNetworkReply& requestReply);
private slots:
void processSettingsRequestPacket(QSharedPointer message);
@@ -105,26 +113,36 @@ private:
void validateDescriptorsMap();
// these cause calls to metaverse's group api
- void requestMissingGroupIDs();
- void getGroupID(const QString& groupname);
- NodePermissionsPointer lookupGroupByID(const QUuid& id);
- void getGroupRanks(const QUuid& groupID);
+ void apiRefreshGroupInformation();
+ void apiGetGroupID(const QString& groupName);
+ void apiGetGroupRanks(const QUuid& groupID);
void packPermissionsForMap(QString mapName, NodePermissionsMap& agentPermissions, QString keyPath);
void packPermissions();
void unpackPermissions();
+ bool ensurePermissionsForGroupRanks();
- NodePermissionsMap _standardAgentPermissions; // anonymous, logged-in, localhost
+ NodePermissionsMap _standardAgentPermissions; // anonymous, logged-in, localhost, friend-of-domain-owner
NodePermissionsMap _agentPermissions; // specific account-names
+
NodePermissionsMap _groupPermissions; // permissions granted by membership to specific groups
NodePermissionsMap _groupForbiddens; // permissions denied due to membership in a specific group
- QHash _groupByID; // similar to _groupPermissions but key is group-id rather than name
+ // these are like _groupPermissions and _groupForbiddens but with uuids rather than group-names in the keys
+ QHash _groupPermissionsByUUID;
+ QHash _groupForbiddensByUUID;
+
+ QHash _groupIDs; // keep track of group-name to group-id mappings
+ QHash _groupNames; // keep track of group-id to group-name mappings
// remember the responses to api/v1/groups/%1/ranks
- QHash> _groupRanks;
+ QHash> _groupRanks; // QHash>
+ QHash _groupRanksLastFetched; // when did we last update _groupRanks
// keep track of answers to api queries about which users are in which groups
- QHash> _groupMembership;
+ QHash> _groupMembership; // QHash>
+
+
+ void debugDumpGroupsState();
};
#endif // hifi_DomainServerSettingsManager_h
diff --git a/libraries/networking/src/NodePermissions.cpp b/libraries/networking/src/NodePermissions.cpp
index 023e3cb04a..e16b746b96 100644
--- a/libraries/networking/src/NodePermissions.cpp
+++ b/libraries/networking/src/NodePermissions.cpp
@@ -13,22 +13,27 @@
#include
#include "NodePermissions.h"
-QString NodePermissions::standardNameLocalhost = QString("localhost");
-QString NodePermissions::standardNameLoggedIn = QString("logged-in");
-QString NodePermissions::standardNameAnonymous = QString("anonymous");
-QString NodePermissions::standardNameFriends = QString("friends");
+NodePermissionsKey NodePermissions::standardNameLocalhost = NodePermissionsKey("localhost", 0);
+NodePermissionsKey NodePermissions::standardNameLoggedIn = NodePermissionsKey("logged-in", 0);
+NodePermissionsKey NodePermissions::standardNameAnonymous = NodePermissionsKey("anonymous", 0);
+NodePermissionsKey NodePermissions::standardNameFriends = NodePermissionsKey("friends", 0);
QStringList NodePermissions::standardNames = QList()
- << NodePermissions::standardNameLocalhost
- << NodePermissions::standardNameLoggedIn
- << NodePermissions::standardNameAnonymous
- << NodePermissions::standardNameFriends;
+ << NodePermissions::standardNameLocalhost.first
+ << NodePermissions::standardNameLoggedIn.first
+ << NodePermissions::standardNameAnonymous.first
+ << NodePermissions::standardNameFriends.first;
NodePermissions::NodePermissions(QMap perms) {
- _id = perms["permissions_id"].toString();
+ _id = perms["permissions_id"].toString().toLower();
if (perms.contains("group_id")) {
- _groupIDSet = true;
_groupID = perms["group_id"].toUuid();
+ if (!_groupID.isNull()) {
+ _groupIDSet = true;
+ }
+ }
+ if (perms.contains("rank")) {
+ _rank = perms["rank"].toInt();
}
permissions = NodePermissions::Permissions();
@@ -41,11 +46,15 @@ NodePermissions::NodePermissions(QMap perms) {
Permission::canConnectPastMaxCapacity : Permission::none;
}
-QVariant NodePermissions::toVariant() {
+QVariant NodePermissions::toVariant(QVector rankNames) {
QMap values;
values["permissions_id"] = _id;
if (_groupIDSet) {
values["group_id"] = _groupID;
+ values["rank"] = _rank;
+ if (rankNames.size() > _rank) {
+ values["rank_name"] = rankNames[_rank];
+ }
}
values["id_can_connect"] = can(Permission::canConnectToDomain);
values["id_can_adjust_locks"] = can(Permission::canAdjustLocks);
@@ -137,7 +146,9 @@ QDataStream& operator>>(QDataStream& in, NodePermissions& perms) {
}
QDebug operator<<(QDebug debug, const NodePermissions& perms) {
- debug.nospace() << "[permissions: " << perms.getID() << " --";
+ debug.nospace() << "[permissions: " << perms.getID() << "/" << perms.getUserName() << " -- ";
+ debug.nospace() << "rank=" << perms.getRank()
+ << ", groupID=" << perms.getGroupID() << "/" << (perms.isGroup() ? "y" : "n");
if (perms.can(NodePermissions::Permission::canConnectToDomain)) {
debug << " connect";
}
diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h
index 1dea560543..411312f708 100644
--- a/libraries/networking/src/NodePermissions.h
+++ b/libraries/networking/src/NodePermissions.h
@@ -20,30 +20,35 @@
class NodePermissions;
using NodePermissionsPointer = std::shared_ptr;
+using NodePermissionsKey = QPair;
+using NodePermissionsKeyList = QList>;
class NodePermissions {
public:
- NodePermissions() { _id = QUuid::createUuid().toString(); }
- NodePermissions(const QString& name) { _id = name.toLower(); }
+ NodePermissions() { _id = QUuid::createUuid().toString(); _rank = 0; }
+ NodePermissions(const QString& name) { _id = name.toLower(); _rank = 0; }
+ NodePermissions(const NodePermissionsKey& key) { _id = key.first.toLower(); _rank = key.second; }
NodePermissions(QMap perms);
- QString getID() const { return _id; }
+ QString getID() const { return _id; } // a user-name or a group-name, not verified
+ int getRank() const { return _rank; }
+ NodePermissionsKey getKey() const { return NodePermissionsKey(_id, _rank); }
- // the _id member isn't authenticated and _username is.
+ // the _id member isn't authenticated/verified and _username is.
void setUserName(QString userName) { _userName = userName.toLower(); }
- QString getUserName() { return _userName; }
+ QString getUserName() const { return _userName; }
- void setGroupID(QUuid groupID) { _groupID = groupID; if (!groupID.isNull()) { _groupIDSet = true; } }
- QUuid getGroupID() { return _groupID; }
- bool isGroup() { return _groupIDSet; }
+ void setGroupID(QUuid groupID) { _groupID = groupID; if (!groupID.isNull()) { _groupIDSet = true; }}
+ QUuid getGroupID() const { return _groupID; }
+ bool isGroup() const { return _groupIDSet; }
bool isAssignment { false };
// these 3 names have special meaning.
- static QString standardNameLocalhost;
- static QString standardNameLoggedIn;
- static QString standardNameAnonymous;
- static QString standardNameFriends;
+ static NodePermissionsKey standardNameLocalhost;
+ static NodePermissionsKey standardNameLoggedIn;
+ static NodePermissionsKey standardNameAnonymous;
+ static NodePermissionsKey standardNameFriends;
static QStringList standardNames;
enum class Permission {
@@ -58,7 +63,7 @@ public:
Q_DECLARE_FLAGS(Permissions, Permission)
Permissions permissions;
- QVariant toVariant();
+ QVariant toVariant(QVector rankNames = QVector());
void setAll(bool value);
@@ -76,6 +81,7 @@ public:
protected:
QString _id;
+ int _rank { 0 }; // 0 unless this is for a group
QString _userName;
bool _groupIDSet { false };
@@ -88,15 +94,28 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(NodePermissions::Permissions)
class NodePermissionsMap {
public:
NodePermissionsMap() { }
- NodePermissionsPointer& operator[](const QString& key) { return _data[key.toLower()]; }
- NodePermissionsPointer operator[](const QString& key) const { return _data.value(key.toLower()); }
- bool contains(const QString& key) const { return _data.contains(key.toLower()); }
- QList keys() const { return _data.keys(); }
- QHash get() { return _data; }
+ NodePermissionsPointer& operator[](const NodePermissionsKey& key) {
+ NodePermissionsKey dataKey(key.first.toLower(), key.second);
+ if (!_data.contains(dataKey)) {
+ _data[dataKey] = NodePermissionsPointer(new NodePermissions(key));
+ }
+ return _data[dataKey];
+ }
+ NodePermissionsPointer operator[](const NodePermissionsKey& key) const {
+ return _data.value(NodePermissionsKey(key.first.toLower(), key.second));
+ }
+ bool contains(const NodePermissionsKey& key) const {
+ return _data.contains(NodePermissionsKey(key.first.toLower(), key.second));
+ }
+ bool contains(const QString& keyFirst, int keySecond) const {
+ return _data.contains(NodePermissionsKey(keyFirst.toLower(), keySecond));
+ }
+ QList keys() const { return _data.keys(); }
+ QHash get() { return _data; }
void clear() { _data.clear(); }
private:
- QHash _data;
+ QHash _data;
};