From 36c8fa16c012dd18012f0c8921fa93c4fbd53b5c Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 00:53:40 +0200 Subject: [PATCH 1/2] Implements group based access restrictions for parcels of land. Because of caching there can be a delay of up to 30 seconds until the access rights are effectively changed for a user. --- .../CoreModules/World/Land/LandObject.cs | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a0ed5a5274..9808ebf95a 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -56,6 +56,12 @@ namespace OpenSim.Region.CoreModules.World.Land protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); + protected IGroupsModule m_groupsModule; + protected const uint PARCEL_FLAG_USE_ACCESS_GROUP = 0x100; // parcel limits access to a group + protected Dictionary m_isGroupMemberCache = new Dictionary(); + protected Dictionary m_notGroupMemberCache = new Dictionary(); + protected const long m_groupMemberCacheTimeout = 30; // cache invalidation after 30 seconds + public bool[,] LandBitmap { get { return m_landBitmap; } @@ -132,6 +138,8 @@ namespace OpenSim.Region.CoreModules.World.Land else LandData.GroupID = UUID.Zero; LandData.IsGroupOwned = is_group_owned; + + m_groupsModule = scene.RequestModuleInterface(); } #endregion @@ -460,7 +468,55 @@ namespace OpenSim.Region.CoreModules.World.Land if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0) return false; - return (!IsInLandAccessList(avatar)); + if (IsInLandAccessList(avatar)) + return false; + + UUID groupID = LandData.GroupID; + + if ((m_groupsModule != null) && (groupID != UUID.Zero) && ((LandData.Flags & PARCEL_FLAG_USE_ACCESS_GROUP) == PARCEL_FLAG_USE_ACCESS_GROUP)) + { + long now = Util.UnixTimeSinceEpoch(); + + if (m_isGroupMemberCache.ContainsKey(avatar)) + { + if (now - m_isGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? + { + m_isGroupMemberCache[avatar] = now; + return false; + } + else + m_isGroupMemberCache.Remove(avatar); + } + + if (m_notGroupMemberCache.ContainsKey(avatar)) + { + if (now - m_notGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? + { + // m_notGroupMemberCache[avatar] = now; + return true; + } + else + m_notGroupMemberCache.Remove(avatar); + } + + GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(avatar); + + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + { + if (groupID == GroupMembership[i].GroupID) + { + m_isGroupMemberCache[avatar] = now; + return false; + } + } + } + + m_notGroupMemberCache[avatar] = now; + } + + return true; } public bool IsInLandAccessList(UUID avatar) From a5d6b624f6e2abf8dd3e66b2f1f6924f5f1125d1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 5 Apr 2012 00:45:58 +0100 Subject: [PATCH 2/2] Simplify group access checks and break them out into a separate method. Use existing cache if the avatar is within the region and use an ExpiringCache to cache status if the avatar is not in the region. The 30 second delay now applies to scripted objects ony and only when the owner is not present. --- .../CoreModules/World/Land/LandObject.cs | 106 ++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 9808ebf95a..c532d0d645 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -56,11 +56,8 @@ namespace OpenSim.Region.CoreModules.World.Land protected List primsOverMe = new List(); protected Dictionary m_listTransactions = new Dictionary(); - protected IGroupsModule m_groupsModule; - protected const uint PARCEL_FLAG_USE_ACCESS_GROUP = 0x100; // parcel limits access to a group - protected Dictionary m_isGroupMemberCache = new Dictionary(); - protected Dictionary m_notGroupMemberCache = new Dictionary(); - protected const long m_groupMemberCacheTimeout = 30; // cache invalidation after 30 seconds + protected ExpiringCache m_groupMemberCache = new ExpiringCache(); + protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds public bool[,] LandBitmap { @@ -138,8 +135,6 @@ namespace OpenSim.Region.CoreModules.World.Land else LandData.GroupID = UUID.Zero; LandData.IsGroupOwned = is_group_owned; - - m_groupsModule = scene.RequestModuleInterface(); } #endregion @@ -425,6 +420,48 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } + public bool HasGroupAccess(UUID avatar) + { + if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) + { + ScenePresence sp; + if (!m_scene.TryGetScenePresence(avatar, out sp)) + { + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; + + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) + return false; + + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) + { + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } + + foreach (GroupMembershipData d in membership) + { + if (d.GroupID == LandData.GroupID) + { + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } + + if (!sp.ControllingClient.IsGroupMember(LandData.GroupID)) + return false; + + return true; + } + return false; + } + public bool IsBannedFromLand(UUID avatar) { ExpireAccessList(); @@ -456,6 +493,9 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsRestrictedFromLand(UUID avatar) { + if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0) + return false; + if (m_scene.Permissions.IsAdministrator(avatar)) return false; @@ -465,58 +505,10 @@ namespace OpenSim.Region.CoreModules.World.Land if (avatar == LandData.OwnerID) return false; - if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0) + if (HasGroupAccess(avatar)) return false; - if (IsInLandAccessList(avatar)) - return false; - - UUID groupID = LandData.GroupID; - - if ((m_groupsModule != null) && (groupID != UUID.Zero) && ((LandData.Flags & PARCEL_FLAG_USE_ACCESS_GROUP) == PARCEL_FLAG_USE_ACCESS_GROUP)) - { - long now = Util.UnixTimeSinceEpoch(); - - if (m_isGroupMemberCache.ContainsKey(avatar)) - { - if (now - m_isGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? - { - m_isGroupMemberCache[avatar] = now; - return false; - } - else - m_isGroupMemberCache.Remove(avatar); - } - - if (m_notGroupMemberCache.ContainsKey(avatar)) - { - if (now - m_notGroupMemberCache[avatar] <= m_groupMemberCacheTimeout) // invalid? - { - // m_notGroupMemberCache[avatar] = now; - return true; - } - else - m_notGroupMemberCache.Remove(avatar); - } - - GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(avatar); - - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - { - if (groupID == GroupMembership[i].GroupID) - { - m_isGroupMemberCache[avatar] = now; - return false; - } - } - } - - m_notGroupMemberCache[avatar] = now; - } - - return true; + return !IsInLandAccessList(avatar); } public bool IsInLandAccessList(UUID avatar)