When creating an OAR, optionally exclude objects according to their permissions

remove-scene-viewer
Oren Hurvitz 2011-09-11 20:52:35 +03:00 committed by Justin Clark-Casey (justincc)
parent 517932722b
commit 7f318277f1
6 changed files with 217 additions and 44 deletions

View File

@ -117,6 +117,7 @@ what it is today.
* nornalbion
* Omar Vera Ustariz (IBM)
* openlifegrid.com
* Oren Hurvitz (Kitely)
* otakup0pe
* ralphos
* RemedyTomm

View File

@ -269,13 +269,15 @@ namespace OpenSim
m_console.Commands.AddCommand("region", false, "save oar",
//"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
"save oar [-p|--profile=<url>] [--noassets] [<OAR path>]",
"save oar [-p|--profile=<url>] [--noassets] [--perm=<permissions>] [<OAR path>]",
"Save a region's data to an OAR archive.",
// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
"-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine
+ "--noassets stops assets being saved to the OAR." + Environment.NewLine
+ "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine
+ " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
+ "The OAR path must be a filesystem path."
+ " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine
+ "--noassets stops assets being saved to the OAR.",
+ " If this is not given then the oar is saved to region.oar in the current directory.",
SaveOar);
m_console.Commands.AddCommand("region", false, "edit scale",

View File

@ -128,6 +128,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
EntityBase[] entities = m_scene.GetEntities();
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
string checkPermissions = null;
int numObjectsSkippedPermissions = 0;
Object temp;
if (options.TryGetValue("checkPermissions", out temp))
checkPermissions = (string)temp;
// Filter entities so that we only have scene objects.
// FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
// end up having to do this
@ -138,7 +144,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
sceneObjects.Add((SceneObjectGroup)entity);
{
if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
{
// The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
++numObjectsSkippedPermissions;
}
else
{
sceneObjects.Add(sceneObject);
}
}
}
}
@ -160,6 +176,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
}
if (numObjectsSkippedPermissions > 0)
{
m_log.DebugFormat(
"[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
numObjectsSkippedPermissions);
}
// Make sure that we also request terrain texture assets
RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
@ -210,6 +233,83 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
}
/// <summary>
/// Checks whether the user has permission to export an object group to an OAR.
/// </summary>
/// <param name="user">The user</param>
/// <param name="objGroup">The object group</param>
/// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
/// <returns>Whether the user is allowed to export the object to an OAR</returns>
private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
{
if (checkPermissions == null)
return true;
IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
if (module == null)
return true; // this shouldn't happen
// Check whether the user is permitted to export all of the parts in the SOG. If any
// part can't be exported then the entire SOG can't be exported.
bool permitted = true;
//int primNumber = 1;
foreach (SceneObjectPart obj in objGroup.Parts)
{
uint perm;
PermissionClass permissionClass = module.GetPermissionClass(user, obj);
switch (permissionClass)
{
case PermissionClass.Owner:
perm = obj.BaseMask;
break;
case PermissionClass.Group:
perm = obj.GroupMask | obj.EveryoneMask;
break;
case PermissionClass.Everyone:
default:
perm = obj.EveryoneMask;
break;
}
bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
// Special case: if Everyone can copy the object then this implies it can also be
// Transferred.
// However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
// always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
// does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
if (permissionClass != PermissionClass.Owner)
{
canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
}
bool partPermitted = true;
if (checkPermissions.Contains("C") && !canCopy)
partPermitted = false;
if (checkPermissions.Contains("T") && !canTransfer)
partPermitted = false;
//string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
//m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, permitted={8}",
// name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
// permissionClass, checkPermissions, canCopy, canTransfer, permitted);
if (!partPermitted)
{
permitted = false;
break;
}
//++primNumber;
}
return permitted;
}
/// <summary>
/// Create the control file for the most up to date archive
/// </summary>

View File

@ -128,6 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// ops.Add("v|version=", delegate(string v) { options["version"] = v; });
ops.Add("p|profile=", delegate(string v) { options["profile"] = v; });
ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
List<string> mainParams = ops.Parse(cmdparams);

View File

@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.World.Permissions
{
public class PermissionsModule : IRegionModule
public class PermissionsModule : IRegionModule, IPermissionsModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
else
m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
scene.RegisterModuleInterface<IPermissionsModule>(this);
//Register functions with Scene External Checks!
m_scene.Permissions.OnBypassPermissions += BypassPermissions;
m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions;
@ -574,47 +576,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (objectOwner != UUID.Zero)
objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner;
if (m_bypassPermissions)
return objectOwnerMask;
PermissionClass permissionClass = GetPermissionClass(user, task);
// Object owners should be able to edit their own content
if (user == objectOwner)
return objectOwnerMask;
if (IsFriendWithPerms(user, objectOwner))
switch (permissionClass)
{
case PermissionClass.Owner:
return objectOwnerMask;
}
// Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
{
return objectOwnerMask;
}
// Admin should be able to edit anything in the sim (including admin objects)
if (IsAdministrator(user))
{
return objectOwnerMask;
}
// Users should be able to edit what is over their land.
Vector3 taskPos = task.AbsolutePosition;
ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
{
// Admin objects should not be editable by the above
if (!IsAdministrator(objectOwner))
{
return objectOwnerMask;
}
}
// Group permissions
if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
case PermissionClass.Group:
return objectGroupMask | objectEveryoneMask;
case PermissionClass.Everyone:
default:
return objectEveryoneMask;
}
}
private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask)
{
@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return objectFlagsMask;
}
public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj)
{
if (obj == null)
return PermissionClass.Everyone;
if (m_bypassPermissions)
return PermissionClass.Owner;
// Object owners should be able to edit their own content
UUID objectOwner = obj.OwnerID;
if (user == objectOwner)
return PermissionClass.Owner;
if (IsFriendWithPerms(user, objectOwner))
return PermissionClass.Owner;
// Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
return PermissionClass.Owner;
// Admin should be able to edit anything in the sim (including admin objects)
if (IsAdministrator(user))
return PermissionClass.Owner;
// Users should be able to edit what is over their land.
Vector3 taskPos = obj.AbsolutePosition;
ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
{
// Admin objects should not be editable by the above
if (!IsAdministrator(objectOwner))
return PermissionClass.Owner;
}
// Group permissions
if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0))
return PermissionClass.Group;
return PermissionClass.Everyone;
}
/// <summary>
/// General permissions checks for any operation involving an object. These supplement more specific checks
/// implemented by callers.

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
/// <value>
/// Which set of permissions a user has.
/// </value>
public enum PermissionClass
{
Owner,
Group,
Everyone
};
public interface IPermissionsModule
{
/// <summary>
/// Returns the type of permissions that the user has over an object.
/// </summary>
/// <param name="user">The user</param>
/// <param name="obj">The object</param>
/// <returns>The type of permissions the user has over the object</returns>
PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj);
}
}