Merge pull request #8118 from sethalves/tmp-rez-cap-rather-than-reject

cap lifetime rather than reject edits from nodes which only have tmp-rez rights
This commit is contained in:
Brad Hefta-Gaub 2016-06-24 14:08:29 -07:00 committed by GitHub
commit 2e8f6c2cc6
5 changed files with 31 additions and 47 deletions

View file

@ -384,7 +384,7 @@
"name": "standard_permissions",
"type": "table",
"label": "Domain-Wide User Permissions",
"help": "Indicate which users or groups can have which <a data-toggle='tooltip' data-html=true title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let&rsquo;s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>domain-wide permissions</a>.",
"help": "Indicate which users or groups can have which <a data-toggle='tooltip' data-html=true title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let&rsquo;s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>domain-wide permissions</a>.",
"caption": "Standard Permissions",
"can_add_new_rows": false,
@ -394,7 +394,7 @@
"span": 1
},
{
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let&rsquo;s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let&rsquo;s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
"span": 6
}
],
@ -463,7 +463,7 @@
"span": 1
},
{
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let&rsquo;s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether a user can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether a user change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether a user can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether a user can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether a user can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether a user can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Note that permissions assigned to a specific user will supersede any parameter-level permissions that might otherwise apply to that user. Additionally, if more than one parameter is applicable to a given user, the permissions given to that user will be the sum of all applicable parameters. For example, let&rsquo;s say only localhost users can connect and only logged in users can lock and unlock entities. If a user is both logged in and on localhost then they will be able to both connect and lock/unlock entities.</p>'>?</a>",
"span": 6
}
],

View file

@ -179,6 +179,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
}
entity->setLastBroadcast(usecTimestampNow());
propertiesWithSimID.setLastEdited(entity->getLastEdited());
} else {
qCDebug(entities) << "script failed to add new Entity to local Octree";
success = false;
@ -376,6 +377,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
properties.setQueryAACube(entity->getQueryAACube());
}
entity->setLastBroadcast(usecTimestampNow());
properties.setLastEdited(entity->getLastEdited());
// if we've moved an entity with children, check/update the queryAACube of all descendents and tell the server
// if they've changed.

View file

@ -130,16 +130,13 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
EntityItemProperties properties = origProperties;
bool allowLockChange;
bool canRezPermanentEntities;
QUuid senderID;
if (senderNode.isNull()) {
auto nodeList = DependencyManager::get<NodeList>();
allowLockChange = nodeList->isAllowedEditor();
canRezPermanentEntities = nodeList->getThisNodeCanRez();
senderID = nodeList->getSessionUUID();
} else {
allowLockChange = senderNode->isAllowedEditor();
canRezPermanentEntities = senderNode->getCanRez();
senderID = senderNode->getUUID();
}
@ -148,14 +145,6 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
return false;
}
if (!canRezPermanentEntities && (entity->getLifetime() != properties.getLifetime())) {
// we don't allow a Node that can't create permanent entities to adjust lifetimes on existing ones
if (properties.lifetimeChanged()) {
qCDebug(entities) << "Refusing disallowed entity lifetime adjustment.";
return false;
}
}
// enforce support for locked entities. If an entity is currently locked, then the only
// property we allow you to change is the locked property.
if (entity->getLocked()) {
@ -321,26 +310,9 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
return true;
}
bool EntityTree::permissionsAllowRez(const EntityItemProperties& properties, bool canRez, bool canRezTmp) {
float lifeTime = properties.getLifetime();
if (lifeTime == ENTITY_ITEM_IMMORTAL_LIFETIME || lifeTime > _maxTmpEntityLifetime) {
// this is an attempt to rez a permanent or non-temporary entity.
if (!canRez) {
return false;
}
} else {
// this is an attempt to rez a temporary entity.
if (!canRezTmp) {
return false;
}
}
return true;
}
EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result = NULL;
EntityItemProperties props = properties;
auto nodeList = DependencyManager::get<NodeList>();
if (!nodeList) {
@ -348,16 +320,8 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
return nullptr;
}
bool clientOnly = properties.getClientOnly();
if (!clientOnly && getIsClient() &&
!permissionsAllowRez(properties, nodeList->getThisNodeCanRez(), nodeList->getThisNodeCanRezTmp())) {
// if our Node isn't allowed to create entities in this domain, don't try.
return nullptr;
}
bool recordCreationTime = false;
if (properties.getCreated() == UNKNOWN_CREATED_TIME) {
if (props.getCreated() == UNKNOWN_CREATED_TIME) {
// the entity's creation time was not specified in properties, which means this is a NEW entity
// and we must record its creation time
recordCreationTime = true;
@ -372,8 +336,8 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
}
// construct the instance of the entity
EntityTypes::EntityType type = properties.getType();
result = EntityTypes::constructEntityItem(type, entityID, properties);
EntityTypes::EntityType type = props.getType();
result = EntityTypes::constructEntityItem(type, entityID, props);
if (result) {
if (recordCreationTime) {
@ -890,6 +854,13 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
QString::number((int)pos.y) + "," +
QString::number((int)pos.z);
}
if (properties.lifetimeChanged()) {
int index = changedProperties.indexOf("lifetime");
if (index >= 0) {
float value = properties.getLifetime();
changedProperties[index] = QString("lifetime:") + QString::number((int)value);
}
}
}
int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
@ -922,11 +893,23 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
EntityItemID entityItemID;
EntityItemProperties properties;
startDecode = usecTimestampNow();
bool validEditPacket = EntityItemProperties::decodeEntityEditPacket(editData, maxLength, processedBytes,
entityItemID, properties);
endDecode = usecTimestampNow();
const quint64 LAST_EDITED_SERVERSIDE_BUMP = 1; // usec
if (!senderNode->getCanRez() && senderNode->getCanRezTmp()) {
// this node is only allowed to rez temporary entities. if need be, cap the lifetime.
if (properties.getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME ||
properties.getLifetime() > _maxTmpEntityLifetime) {
properties.setLifetime(_maxTmpEntityLifetime);
// also bump up the lastEdited time of the properties so that the interface that created this edit
// will accept our adjustment to lifetime back into its own entity-tree.
properties.setLastEdited(properties.getLastEdited() + LAST_EDITED_SERVERSIDE_BUMP);
}
}
// If we got a valid edit packet, then it could be a new entity or it could be an update to
// an existing entity... handle appropriately
if (validEditPacket) {
@ -955,7 +938,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
endUpdate = usecTimestampNow();
_totalUpdates++;
} else if (message.getType() == PacketType::EntityAdd) {
if (permissionsAllowRez(properties, senderNode->getCanRez(), senderNode->getCanRezTmp())) {
if (senderNode->getCanRez() || senderNode->getCanRezTmp()) {
// this is a new entity... assign a new entityID
properties.setCreated(properties.getLastEdited());
startCreate = usecTimestampNow();

View file

@ -64,7 +64,6 @@ public:
void setEntityMaxTmpLifetime(float maxTmpEntityLifetime) { _maxTmpEntityLifetime = maxTmpEntityLifetime; }
bool permissionsAllowRez(const EntityItemProperties& properties, bool canRez, bool canRezTmp);
/// Implements our type specific root element factory
virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL) override;

View file

@ -334,7 +334,7 @@ var toolBar = (function() {
that.setActive = function(active) {
if (active != isActive) {
if (active && !Entities.canAdjustLocks()) {
if (active && !Entities.canRez() && !Entities.canRezTmp()) {
Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG);
} else {
Messages.sendLocalMessage("edit-events", JSON.stringify({