split permissions into two sets, one for 'standard' ones and one for specific users

This commit is contained in:
Seth Alves 2016-06-06 10:39:47 -07:00
parent 880c4f18b5
commit a4e4093a18
5 changed files with 165 additions and 39 deletions

View file

@ -56,6 +56,7 @@
"label": "Paths",
"help": "Clients can enter a path to reach an exact viewpoint in your domain.<br/>Add rows to the table below to map a path to a viewpoint.<br/>The index path ( / ) is where clients will enter if they do not enter an explicit path.",
"type": "table",
"can_add_new_rows": true,
"key": {
"name": "path",
"label": "Path",
@ -96,10 +97,11 @@
"advanced": false
},
{
"name": "permissions",
"name": "standard_permissions",
"type": "table",
"label": "Domain-Wide User Permissions",
"help": "Indicate which users or groups can have which domain-wide permissions.",
"label": "Domain-Wide Permissions",
"help": "Standard Permissions:",
"can_add_new_rows": false,
"columns": [
{
@ -152,6 +154,61 @@
"non-deletable-row-key": "permissions_id",
"non-deletable-row-values": ["localhost", "anonymous", "logged-in"]
},
{
"name": "permissions",
"type": "table",
"help": "Permissions for Specific Users:",
"can_add_new_rows": true,
"columns": [
{
"name": "permissions_id",
"label": "User/Group"
},
{
"name": "id_can_connect",
"label": "Connect",
"type": "checkbox",
"editable": true,
"default": true
},
{
"name": "id_can_adjust_locks",
"label": "Lock/Unlock",
"type": "checkbox",
"editable": true,
"default": false
},
{
"name": "id_can_rez",
"label": "Rez",
"type": "checkbox",
"editable": true,
"default": false
},
{
"name": "id_can_rez_tmp",
"label": "Rez Temp",
"type": "checkbox",
"editable": true,
"default": false
},
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
"type": "checkbox",
"editable": true,
"default": false
},
{
"name": "id_can_connect_past_max_capacity",
"label": "Ignore Max Capacity",
"type": "checkbox",
"editable": true,
"default": false
}
]
}
]
},
@ -164,6 +221,8 @@
"type": "table",
"label": "Persistent Scripts",
"help": "Add the URLs for scripts that you would like to ensure are always running in your domain.",
"can_add_new_rows": true,
"columns": [
{
"name": "url",
@ -248,6 +307,8 @@
"label": "Zones",
"help": "In this table you can define a set of zones in which you can specify various audio properties.",
"numbered": false,
"can_add_new_rows": true,
"key": {
"name": "name",
"label": "Name",
@ -299,6 +360,8 @@
"help": "In this table you can set custom attenuation coefficients between audio zones",
"numbered": true,
"can_order": true,
"can_add_new_rows": true,
"columns": [
{
"name": "source",
@ -326,6 +389,8 @@
"label": "Reverb Settings",
"help": "In this table you can set reverb levels for audio zones. For a medium-sized (e.g., 100 square meter) meeting room, try a decay time of around 1.5 seconds and a wet/dry mix of 25%. For an airplane hangar or cathedral, try a decay time of 4 seconds and a wet/dry mix of 50%.",
"numbered": true,
"can_add_new_rows": true,
"columns": [
{
"name": "zone",
@ -447,6 +512,8 @@
"label": "Backup Rules",
"help": "In this table you can define a set of rules for how frequently to backup copies of your entites content file.",
"numbered": false,
"can_add_new_rows": true,
"default": [
{"Name":"Half Hourly Rolling","backupInterval":1800,"format":".backup.halfhourly.%N","maxBackupVersions":5},
{"Name":"Daily Rolling","backupInterval":86400,"format":".backup.daily.%N","maxBackupVersions":7},

View file

@ -1015,7 +1015,7 @@ function makeTable(setting, keypath, setting_value, isLocked) {
}
// populate inputs in the table for new values
if (!isLocked && !setting.read_only) {
if (!isLocked && !setting.read_only && setting.can_add_new_rows) {
html += makeTableInputs(setting)
}
html += "</table>"
@ -1052,8 +1052,8 @@ function makeTableInputs(setting) {
if (setting.can_order) {
html += "<td class='" + Settings.REORDER_BUTTONS_CLASSES + "'></td>"
}
html += "<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES +
"'><a href='javascript:void(0);' class='glyphicon glyphicon-plus " + Settings.ADD_ROW_BUTTON_CLASS + "'></a></td>"
html += "<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES +
"'><a href='javascript:void(0);' class='glyphicon glyphicon-plus " + Settings.ADD_ROW_BUTTON_CLASS + "'></a></td>"
html += "</tr>"
return html

View file

@ -189,7 +189,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
bool isLocalUser =
(senderHostAddress == limitedNodeList->getLocalSockAddr().getAddress() || senderHostAddress == QHostAddress::LocalHost);
if (isLocalUser) {
userPerms |= _server->_settingsManager.getPermissionsForName(NodePermissions::standardNameLocalhost);
userPerms |= _server->_settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLocalhost);
qDebug() << "user-permissions: is local user, so:" << userPerms;
}

View file

@ -206,18 +206,18 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
QStringList allowedEditors = valueOrDefaultValueForKeyPath(ALLOWED_EDITORS_SETTINGS_KEYPATH).toStringList();
bool onlyEditorsAreRezzers = valueOrDefaultValueForKeyPath(EDITORS_ARE_REZZERS_KEYPATH).toBool();
_agentPermissions[NodePermissions::standardNameLocalhost].reset(
_standardAgentPermissions[NodePermissions::standardNameLocalhost].reset(
new NodePermissions(NodePermissions::standardNameLocalhost));
_agentPermissions[NodePermissions::standardNameLocalhost]->setAll(true);
_agentPermissions[NodePermissions::standardNameAnonymous].reset(
_standardAgentPermissions[NodePermissions::standardNameLocalhost]->setAll(true);
_standardAgentPermissions[NodePermissions::standardNameAnonymous].reset(
new NodePermissions(NodePermissions::standardNameAnonymous));
_agentPermissions[NodePermissions::standardNameLoggedIn].reset(
_standardAgentPermissions[NodePermissions::standardNameLoggedIn].reset(
new NodePermissions(NodePermissions::standardNameLoggedIn));
if (isRestrictedAccess) {
// only users in allow-users list can connect
_agentPermissions[NodePermissions::standardNameAnonymous]->canConnectToDomain = false;
_agentPermissions[NodePermissions::standardNameLoggedIn]->canConnectToDomain = false;
_standardAgentPermissions[NodePermissions::standardNameAnonymous]->canConnectToDomain = false;
_standardAgentPermissions[NodePermissions::standardNameLoggedIn]->canConnectToDomain = false;
} // else anonymous and logged-in retain default of canConnectToDomain = true
foreach (QString allowedUser, allowedUsers) {
@ -237,14 +237,20 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
_agentPermissions[allowedEditor]->canAdjustLocks = true;
}
foreach (QString userName, _agentPermissions.keys()) {
if (onlyEditorsAreRezzers) {
_agentPermissions[userName]->canRezPermanentEntities = _agentPermissions[userName]->canAdjustLocks;
} else {
_agentPermissions[userName]->canRezPermanentEntities = true;
QList<QHash<QString, NodePermissionsPointer>> permissionsSets;
permissionsSets << _standardAgentPermissions << _agentPermissions;
foreach (auto permissionsSet, permissionsSets) {
foreach (QString userName, permissionsSet.keys()) {
if (onlyEditorsAreRezzers) {
permissionsSet[userName]->canRezPermanentEntities = permissionsSet[userName]->canAdjustLocks;
} else {
permissionsSet[userName]->canRezPermanentEntities = true;
}
}
}
packPermissions(argumentList);
_standardAgentPermissions.clear();
_agentPermissions.clear();
}
}
@ -255,22 +261,36 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
appSettings.setValue(JSON_SETTINGS_VERSION_KEY, _descriptionVersion);
}
void DomainServerSettingsManager::packPermissions(const QStringList& argumentList) {
// transfer details from _agentPermissions to _configMap
void DomainServerSettingsManager::packPermissionsForMap(const QStringList& argumentList,
QString mapName,
QHash<QString, NodePermissionsPointer> agentPermissions,
QString keyPath) {
QVariant* security = valueForKeyPath(_configMap.getUserConfig(), "security");
QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_PERMISSIONS_KEYPATH);
// save settings for anonymous / logged-in / localhost
QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath);
if (!permissions || !permissions->canConvert(QMetaType::QVariantList)) {
QVariantMap securityMap = security->toMap();
QVariantList userList;
securityMap["permissions"] = userList;
securityMap[mapName] = userList;
_configMap.getUserConfig()["security"] = securityMap;
permissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_PERMISSIONS_KEYPATH);
permissions = valueForKeyPath(_configMap.getUserConfig(), keyPath);
}
QVariantList* permissionsList = reinterpret_cast<QVariantList*>(permissions);
foreach (QString userName, _agentPermissions.keys()) {
*permissionsList += _agentPermissions[userName]->toVariant();
(*permissionsList).clear();
foreach (QString userName, agentPermissions.keys()) {
*permissionsList += agentPermissions[userName]->toVariant();
}
}
void DomainServerSettingsManager::packPermissions(const QStringList& argumentList) {
// transfer details from _agentPermissions to _configMap
packPermissionsForMap(argumentList, "standard_permissions", _standardAgentPermissions, AGENT_STANDARD_PERMISSIONS_KEYPATH);
// save settings for specific users
packPermissionsForMap(argumentList, "permissions", _agentPermissions, AGENT_PERMISSIONS_KEYPATH);
persistToFile();
_configMap.loadMasterAndUserConfig(argumentList);
}
@ -281,25 +301,43 @@ void DomainServerSettingsManager::unpackPermissions(const QStringList& argumentL
bool foundLocalhost = false;
bool foundAnonymous = false;
bool foundLoggedIn = false;
bool needPack = false;
QVariant* standardPermissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_STANDARD_PERMISSIONS_KEYPATH);
if (!standardPermissions || !standardPermissions->canConvert(QMetaType::QVariantList)) {
qDebug() << "failed to extract standard permissions from settings.";
return;
}
QVariant* permissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_PERMISSIONS_KEYPATH);
if (!permissions || !permissions->canConvert(QMetaType::QVariantList)) {
qDebug() << "failed to extract permissions from settings.";
return;
}
QList<QVariant> permissionsList = permissions->toList();
// QVariantList* permissionsList = reinterpret_cast<QVariantList*>(permissions);
foreach (QVariant permsHash, permissionsList) {
QList<QVariant> standardPermissionsList = standardPermissions->toList();
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);
if (_standardAgentPermissions.contains(id)) {
qDebug() << "duplicate name in standard permissions table: " << id;
_standardAgentPermissions[id] |= perms;
needPack = true;
} else {
_standardAgentPermissions[id] = perms;
}
}
QList<QVariant> permissionsList = permissions->toList();
foreach (QVariant permsHash, permissionsList) {
NodePermissionsPointer perms { new NodePermissions(permsHash.toMap()) };
QString id = perms->getID();
if (_agentPermissions.contains(id)) {
qDebug() << "duplicate name in permissions table: " << id;
_agentPermissions[id] |= perms;
needPack = true;
} else {
_agentPermissions[id] = perms;
}
@ -309,31 +347,46 @@ void DomainServerSettingsManager::unpackPermissions(const QStringList& argumentL
if (!foundLocalhost) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameLocalhost) };
perms->setAll(true);
_agentPermissions[perms->getID()] = perms;
_standardAgentPermissions[perms->getID()] = perms;
}
if (!foundAnonymous) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameAnonymous) };
_agentPermissions[perms->getID()] = perms;
needPack = true;
}
if (!foundLoggedIn) {
NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameLoggedIn) };
_agentPermissions[perms->getID()] = perms;
needPack = true;
}
if (!foundLocalhost || !foundAnonymous || !foundLoggedIn) {
if (needPack) {
packPermissions(argumentList);
}
#ifdef WANT_DEBUG
qDebug() << "--------------- permissions ---------------------";
QHashIterator<QString, NodePermissionsPointer> i(_agentPermissions);
while (i.hasNext()) {
i.next();
NodePermissionsPointer perms = i.value();
qDebug() << i.key() << perms;
QList<QHash<QString, NodePermissionsPointer>> permissionsSets;
permissionsSets << _standardAgentPermissions << _agentPermissions;
foreach (auto permissionSet, permissionsSets) {
QHashIterator<QString, NodePermissionsPointer> i(permissionSet);
while (i.hasNext()) {
i.next();
NodePermissionsPointer perms = i.value();
qDebug() << i.key() << perms;
}
}
#endif
}
NodePermissions DomainServerSettingsManager::getStandardPermissionsForName(const QString& name) const {
if (_standardAgentPermissions.contains(name)) {
return *(_standardAgentPermissions[name].get());
}
NodePermissions nullPermissions;
nullPermissions.setAll(false);
return nullPermissions;
}
NodePermissions DomainServerSettingsManager::getPermissionsForName(const QString& name) const {
if (_agentPermissions.contains(name)) {
return *(_agentPermissions[name].get());

View file

@ -25,6 +25,7 @@ const QString SETTINGS_PATHS_KEY = "paths";
const QString SETTINGS_PATH = "/settings";
const QString SETTINGS_PATH_JSON = SETTINGS_PATH + ".json";
const QString AGENT_STANDARD_PERMISSIONS_KEYPATH = "security.standard_permissions";
const QString AGENT_PERMISSIONS_KEYPATH = "security.permissions";
class DomainServerSettingsManager : public QObject {
@ -40,7 +41,9 @@ public:
QVariantMap& getUserSettingsMap() { return _configMap.getUserConfig(); }
QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); }
bool haveStandardPermissionsForName(const QString& name) const { return _standardAgentPermissions.contains(name); }
bool havePermissionsForName(const QString& name) const { return _agentPermissions.contains(name); }
NodePermissions getStandardPermissionsForName(const QString& name) const;
NodePermissions getPermissionsForName(const QString& name) const;
QStringList getAllNames() { return _agentPermissions.keys(); }
@ -62,9 +65,12 @@ private:
friend class DomainServer;
void packPermissionsForMap(const QStringList& argumentList, QString mapName,
QHash<QString, NodePermissionsPointer> agentPermissions, QString keyPath);
void packPermissions(const QStringList& argumentList);
void unpackPermissions(const QStringList& argumentList);
QHash<QString, NodePermissionsPointer> _agentPermissions;
QHash<QString, NodePermissionsPointer> _standardAgentPermissions; // anonymous, logged-in, localhost
QHash<QString, NodePermissionsPointer> _agentPermissions; // specific account-names
};
#endif // hifi_DomainServerSettingsManager_h