From 36c8fa16c012dd18012f0c8921fa93c4fbd53b5c Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 00:53:40 +0200 Subject: 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. --- .../Region/CoreModules/World/Land/LandObject.cs | 58 +++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a0ed5a5..9808ebf 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) -- cgit v1.1 From a5d6b624f6e2abf8dd3e66b2f1f6924f5f1125d1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 5 Apr 2012 00:45:58 +0100 Subject: 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. --- .../Region/CoreModules/World/Land/LandObject.cs | 106 ++++++++++----------- 1 file changed, 49 insertions(+), 57 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 9808ebf..c532d0d 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) - return false; - - if (IsInLandAccessList(avatar)) + if (HasGroupAccess(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) -- cgit v1.1 From 600a86bcaeb78089165f7d778661edbfdface047 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 10:02:18 +0200 Subject: Little bug fix in HasGroupAccess, to properly store the case "true" in the cache. --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index c532d0d..ced7b52 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -446,7 +446,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (d.GroupID == LandData.GroupID) { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); return true; } } @@ -454,10 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } - if (!sp.ControllingClient.IsGroupMember(LandData.GroupID)) - return false; - - return true; + return sp.ControllingClient.IsGroupMember(LandData.GroupID); } return false; } -- cgit v1.1 From e4406c846d74212493890a46922292cd7fec2ea5 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 10:25:54 +0200 Subject: Group based access restrictions to parcels require group membership, but not that this group is active for that user. --- .../Region/CoreModules/World/Land/LandObject.cs | 47 ++++++++++------------ 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index ced7b52..a7c7cc5 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -424,37 +424,34 @@ namespace OpenSim.Region.CoreModules.World.Land { 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; + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; - GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); - if (membership == null || membership.Length == 0) - { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) + { + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } - foreach (GroupMembershipData d in membership) - { - if (d.GroupID == LandData.GroupID) - { - m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); - return true; - } - } + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) + { m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); return false; } - return sp.ControllingClient.IsGroupMember(LandData.GroupID); + foreach (GroupMembershipData d in membership) + { + if (d.GroupID == LandData.GroupID) + { + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; } return false; } -- cgit v1.1 From 8f45eb913c6fad38735f00db818e03c4123904aa Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 11:10:05 +0200 Subject: Revert last commit --- .../Region/CoreModules/World/Land/LandObject.cs | 47 ++++++++++++---------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a7c7cc5..ced7b52 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -424,34 +424,37 @@ namespace OpenSim.Region.CoreModules.World.Land { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) { - bool isMember; - if (m_groupMemberCache.TryGetValue(avatar, out isMember)) - return isMember; - - IGroupsModule groupsModule = m_scene.RequestModuleInterface(); - if (groupsModule == null) + ScenePresence sp; + if (!m_scene.TryGetScenePresence(avatar, out sp)) { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; - GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); - if (membership == null || membership.Length == 0) - { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) + return false; - foreach (GroupMembershipData d in membership) - { - if (d.GroupID == LandData.GroupID) + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) { - m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); - return true; + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; } + + foreach (GroupMembershipData d in membership) + { + if (d.GroupID == LandData.GroupID) + { + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; } - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; + + return sp.ControllingClient.IsGroupMember(LandData.GroupID); } return false; } -- cgit v1.1 From 67537f359688bfa592312baf808e9d399fc164fa Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 13:03:57 +0200 Subject: Added missing refresh of group membership client side cache to the groups module. Before memberships of non active groups often were not stored in the cache (n_groupPowers). --- OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 2a15e5d..e669f4c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1294,7 +1294,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); - // Need to send a group membership update to the client // UDP version doesn't seem to behave nicely. But we're going to send it out here // with an empty group membership to hopefully remove groups being displayed due @@ -1305,6 +1304,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); + if (remoteClient.AgentId == dataForAgentID) + remoteClient.RefreshGroupMembership(); } /// -- cgit v1.1