Fixed permissions bug related to friends in PermissionsModule. Added FriendsData[] GetFriends(string principalID) to IFriendsData and FriendInfo[] GetFriends(string PrincipalID) to IFriendsService. Refactored some more in the FriendsModule. Made client get notification of local friends permissions upon HGLogin. HG Friends object permissions work.

This commit is contained in:
Diva Canto
2011-05-21 16:48:00 -07:00
parent 80457111e0
commit 58c53c41de
17 changed files with 376 additions and 301 deletions

View File

@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected List<Scene> m_Scenes = new List<Scene>();
@@ -187,6 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
if (!m_Enabled)
return;
m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
m_Scenes.Add(scene);
scene.RegisterModuleInterface<IFriendsModule>(this);
@@ -221,13 +222,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
#endregion
public uint GetFriendPerms(UUID principalID, UUID friendID)
public virtual uint GetFriendPerms(UUID principalID, UUID friendID)
{
FriendInfo[] friends = GetFriends(principalID);
foreach (FriendInfo fi in friends)
FriendInfo finfo = GetFriend(friends, friendID);
if (finfo != null)
{
if (fi.Friend == friendID.ToString())
return (uint)fi.TheirFlags;
return (uint)finfo.TheirFlags;
}
return 0;
@@ -241,14 +242,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
client.OnTerminateFriendship += OnTerminateFriendship;
client.OnGrantUserRights += OnGrantUserRights;
Util.FireAndForget(delegate { FetchFriendslist(client.AgentId); });
Util.FireAndForget(delegate { FetchFriendslist(client); });
}
/// Fetch the friends list or increment the refcount for the existing
/// friends list
/// Returns true if the list was fetched, false if it wasn't
protected virtual bool FetchFriendslist(UUID agentID)
protected virtual bool FetchFriendslist(IClientAPI client)
{
UUID agentID = client.AgentId;
lock (m_Friends)
{
UserFriendData friendsData;
@@ -261,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
friendsData = new UserFriendData();
friendsData.PrincipalID = agentID;
friendsData.Friends = FriendsService.GetFriends(agentID);
friendsData.Friends = GetFriendsFromService(client);
friendsData.Refcount = 1;
m_Friends[agentID] = friendsData;
@@ -270,6 +272,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
{
return FriendsService.GetFriends(client.AgentId);
}
private void OnClientClosed(UUID agentID, Scene scene)
{
ScenePresence sp = scene.GetScenePresence(agentID);
@@ -293,8 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private void OnMakeRootAgent(ScenePresence sp)
{
UUID agentID = sp.ControllingClient.AgentId;
UpdateFriendsCache(agentID);
UpdateFriendsCache(sp.ControllingClient);
}
private void OnClientLogin(IClientAPI client)
@@ -309,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
m_NeedsListOfFriends.Add(agentID);
}
public void SendFriendsOnlineIfNeeded(IClientAPI client)
public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
{
UUID agentID = client.AgentId;
@@ -317,7 +323,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
lock (m_NeedsListOfFriends)
{
if (!m_NeedsListOfFriends.Remove(agentID))
return;
return false;
}
// Send the friends online
@@ -366,6 +372,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// Finally
LocalFriendshipOffered(agentID, im);
}
return true;
}
protected virtual string FriendshipMessage(string friendID)
@@ -579,7 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
StoreFriendships(agentID, friendID);
// Update the local cache
UpdateFriendsCache(agentID);
UpdateFriendsCache(client);
//
// Notify the friend
@@ -647,7 +655,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
DeleteFriendship(agentID, exfriendID);
// Update local cache
UpdateFriendsCache(agentID);
UpdateFriendsCache(client);
client.SendTerminateFriend(exfriendID);
@@ -679,23 +687,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
{
m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
FriendInfo[] friends = GetFriends(remoteClient.AgentId);
if (friends.Length == 0)
return;
m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
// Let's find the friend in this user's friend list
FriendInfo friend = null;
foreach (FriendInfo fi in friends)
{
if (fi.Friend == target.ToString())
friend = fi;
m_log.DebugFormat("[XXX]: agent {0} has no friends", requester);
return;
}
// Let's find the friend in this user's friend list
FriendInfo friend = GetFriend(friends, target);
if (friend != null) // Found it
{
// Store it on the DB
FriendsService.StoreFriend(requester.ToString(), target.ToString(), rights);
if (!SimpleStore(requester, target, rights))
{
remoteClient.SendAlertMessage("Unable to grant rights.");
return;
}
// Store it in the local cache
int myFlags = friend.MyFlags;
@@ -725,6 +736,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
}
else
m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester);
}
protected virtual bool SimpleStore(UUID agentID, UUID friendID, int rights)
{
FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
return true;
}
protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
{
foreach (FriendInfo fi in friends)
{
if (fi.Friend == friendID.ToString())
return fi;
}
return null;
}
#region Local
@@ -753,7 +782,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
friendClient.SendInstantMessage(im);
// Update the local cache
UpdateFriendsCache(friendID);
UpdateFriendsCache(friendClient);
// we're done
return true;
@@ -786,7 +815,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// the friend in this sim as root agent
friendClient.SendTerminateFriend(exfriendID);
// update local cache
UpdateFriendsCache(exfriendID);
UpdateFriendsCache(friendClient);
// we're done
return true;
}
@@ -816,15 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
// Update local cache
lock (m_Friends)
{
FriendInfo[] friends = GetFriends(friendID);
foreach (FriendInfo finfo in friends)
{
if (finfo.Friend == userID.ToString())
finfo.TheirFlags = rights;
}
}
UpdateLocalCache(userID, friendID, rights);
return true;
}
@@ -866,13 +887,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return EMPTY_FRIENDS;
}
private void UpdateFriendsCache(UUID agentID)
private void UpdateFriendsCache(IClientAPI client)
{
UUID agentID = client.AgentId;
lock (m_Friends)
{
UserFriendData friendsData;
if (m_Friends.TryGetValue(agentID, out friendsData))
friendsData.Friends = FriendsService.GetFriends(agentID);
friendsData.Friends = GetFriendsFromService(client);
}
}
protected void UpdateLocalCache(UUID userID, UUID friendID, int rights)
{
// Update local cache
lock (m_Friends)
{
FriendInfo[] friends = GetFriends(friendID);
FriendInfo finfo = GetFriend(friends, userID);
finfo.TheirFlags = rights;
}
}
}

View File

@@ -58,129 +58,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
#endregion
//public void SendFriendsOnlineIfNeeded(IClientAPI client)
//{
// UUID agentID = client.AgentId;
// // Check if the online friends list is needed
// lock (m_NeedsListOfFriends)
// {
// if (!m_NeedsListOfFriends.Remove(agentID))
// return;
// }
// // Send the friends online
// List<UUID> online = GetOnlineFriends(agentID);
// if (online.Count > 0)
// {
// m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
// client.SendAgentOnline(online.ToArray());
// }
// // Send outstanding friendship offers
// List<string> outstanding = new List<string>();
// FriendInfo[] friends = GetFriends(agentID);
// foreach (FriendInfo fi in friends)
// {
// if (fi.TheirFlags == -1)
// outstanding.Add(fi.Friend);
// }
// GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, String.Empty, agentID, (byte)InstantMessageDialog.FriendshipOffered,
// "Will you be my friend?", true, Vector3.Zero);
// foreach (string fid in outstanding)
// {
// UUID fromAgentID;
// if (!UUID.TryParse(fid, out fromAgentID))
// continue;
// UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
// PresenceInfo presence = null;
// PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
// if (presences != null && presences.Length > 0)
// presence = presences[0];
// if (presence != null)
// im.offline = 0;
// im.fromAgentID = fromAgentID.Guid;
// im.fromAgentName = account.FirstName + " " + account.LastName;
// im.offline = (byte)((presence == null) ? 1 : 0);
// im.imSessionID = im.fromAgentID;
// // Finally
// LocalFriendshipOffered(agentID, im);
// }
//}
//List<UUID> GetOnlineFriends(UUID userID)
//{
// List<string> friendList = new List<string>();
// List<UUID> online = new List<UUID>();
// FriendInfo[] friends = GetFriends(userID);
// foreach (FriendInfo fi in friends)
// {
// if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1))
// friendList.Add(fi.Friend);
// }
// if (friendList.Count > 0)
// {
// PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
// foreach (PresenceInfo pi in presence)
// {
// UUID presenceID;
// if (UUID.TryParse(pi.UserID, out presenceID))
// online.Add(presenceID);
// }
// }
// return online;
//}
//private void StatusNotify(FriendInfo friend, UUID userID, bool online)
//{
// UUID friendID;
// if (UUID.TryParse(friend.Friend, out friendID))
// {
// // Try local
// if (LocalStatusNotification(userID, friendID, online))
// return;
// // The friend is not here [as root]. Let's forward.
// PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
// if (friendSessions != null && friendSessions.Length > 0)
// {
// PresenceInfo friendSession = null;
// foreach (PresenceInfo pinfo in friendSessions)
// if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
// {
// friendSession = pinfo;
// break;
// }
// if (friendSession != null)
// {
// GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
// //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
// m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
// }
// }
// // Friend is not online. Ignore.
// }
// else
// {
// m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
// }
//}
protected override bool FetchFriendslist(UUID agentID)
protected override bool FetchFriendslist(IClientAPI client)
{
if (base.FetchFriendslist(agentID))
if (base.FetchFriendslist(client))
{
UUID agentID = client.AgentId;
// We need to preload the user management cache with the names
// of foreign friends, just like we do with SOPs' creators
foreach (FriendInfo finfo in m_Friends[agentID].Friends)
@@ -204,6 +86,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return false;
}
public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
{
if (base.SendFriendsOnlineIfNeeded(client))
{
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
if (account == null) // foreign
{
FriendInfo[] friends = GetFriends(client.AgentId);
foreach (FriendInfo f in friends)
{
client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
}
}
}
return false;
}
protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
{
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
if (account1 != null)
return base.GetFriendsFromService(client);
// Foreigner
AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
FriendInfo[] finfos = FriendsService.GetFriends(agentUUI);
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
return finfos;
}
protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
{
first = "Unknown"; last = "User";
@@ -249,6 +164,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return "Please confirm this friendship you made while you were away.";
}
protected override bool SimpleStore(UUID agentID, UUID friendID, int rights)
{
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
// Are they both local users?
if (account1 != null && account2 != null)
{
// local grid users
return base.SimpleStore(agentID, friendID, rights);
}
if (account1 != null)
{
FriendInfo[] finfos = GetFriends(agentID);
if (finfos.Length > 0)
{
FriendInfo finfo = GetFriend(finfos, friendID);
FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
return true;
}
}
if (account2 != null)
{
IClientAPI client = LocateClientObject(agentID);
if (client != null)
{
AgentCircuitData acircuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
if (acircuit != null)
{
FriendsService.StoreFriend(Util.ProduceUserUniversalIdentifier(acircuit), friendID.ToString(), rights);
return true;
}
}
}
return false;
}
protected override void StoreBackwards(UUID friendID, UUID agentID)
{
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
@@ -366,6 +320,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// my brain hurts now
}
protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
{
foreach (FriendInfo fi in friends)
{
if (fi.Friend.StartsWith(friendID.ToString()))
return fi;
}
return null;
}
protected override void DeleteFriendship(UUID agentID, UUID exfriendID)
{
base.DeleteFriendship(agentID, exfriendID);
@@ -374,7 +338,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
FriendInfo[] friends = GetFriends(agentID);
foreach (FriendInfo finfo in friends)
{
if (finfo.Friend != exfriendID.ToString() && finfo.Friend.EndsWith(exfriendID.ToString()))
if (finfo.Friend != exfriendID.ToString() && finfo.Friend.StartsWith(exfriendID.ToString()))
{
FriendsService.Delete(agentID, exfriendID.ToString());
// TODO: delete the friendship on the other side
@@ -383,56 +347,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
//private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
//{
// FriendInfo[] friends = GetFriends(remoteClient.AgentId);
// if (friends.Length == 0)
// return;
// m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
// // Let's find the friend in this user's friend list
// FriendInfo friend = null;
// foreach (FriendInfo fi in friends)
// {
// if (fi.Friend == target.ToString())
// friend = fi;
// }
// if (friend != null) // Found it
// {
// // Store it on the DB
// FriendsService.StoreFriend(requester, target.ToString(), rights);
// // Store it in the local cache
// int myFlags = friend.MyFlags;
// friend.MyFlags = rights;
// // Always send this back to the original client
// remoteClient.SendChangeUserRights(requester, target, rights);
// //
// // Notify the friend
// //
// // Try local
// if (LocalGrantRights(requester, target, myFlags, rights))
// return;
// PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() });
// if (friendSessions != null && friendSessions.Length > 0)
// {
// PresenceInfo friendSession = friendSessions[0];
// if (friendSession != null)
// {
// GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
// // TODO: You might want to send the delta to save the lookup
// // on the other end!!
// m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights);
// }
// }
// }
//}
}
}

View File

@@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
// libomv will moan about PrimFlags.ObjectYouOfficer being
// deprecated
#pragma warning disable 0612
#pragma warning disable 0612
objflags &= (uint)
~(PrimFlags.ObjectCopy | // Tells client you can copy the object
PrimFlags.ObjectModify | // tells client you can modify the object
PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
PrimFlags.ObjectModify | // tells client you can modify the object
PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
);
#pragma warning restore 0612
#pragma warning restore 0612
// Creating the three ObjectFlags options for this method to choose from.
// Customize the OwnerMask
@@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (m_bypassPermissions)
return objectOwnerMask;
// Object owners should be able to edit their own content
if (user == objectOwner)
return objectOwnerMask;
if (IsFriendWithPerms(user, objectOwner))
return objectOwnerMask;
if (IsFriendWithPerms(user, objectOwner))
{
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);
@@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions
{
// 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))
return objectGroupMask | objectEveryoneMask;
return objectEveryoneMask;
}
@@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
//
// Nobody but the object owner can set permissions on an object
//
if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
{
return false;
@@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
// Return immediately, so that the administrator can shares group objects
return true;
}
// Friends with benefits should be able to edit the objects too
if (IsFriendWithPerms(currentUser, objectOwner))
// Return immediately, so that the administrator can share objects with friends
return true;
// Users should be able to edit what is over their land.
ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);