OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
GroupsService.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Reflection;
31 using System.Timers;
32 using log4net;
33 using Nini.Config;
34 
35 using OpenMetaverse;
36 using OpenSim.Data;
37 using OpenSim.Framework;
38 using OpenSim.Services.Interfaces;
39 
40 namespace OpenSim.Groups
41 {
43  {
44  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 
46  public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome |
47  GroupPowers.Accountable |
48  GroupPowers.JoinChat |
49  GroupPowers.AllowVoiceChat |
50  GroupPowers.ReceiveNotices |
51  GroupPowers.StartProposal |
52  GroupPowers.VoteOnProposal;
53 
54  public const GroupPowers OwnerPowers = GroupPowers.Accountable |
55  GroupPowers.AllowEditLand |
56  GroupPowers.AllowFly |
57  GroupPowers.AllowLandmark |
58  GroupPowers.AllowRez |
59  GroupPowers.AllowSetHome |
60  GroupPowers.AllowVoiceChat |
61  GroupPowers.AssignMember |
62  GroupPowers.AssignMemberLimited |
63  GroupPowers.ChangeActions |
64  GroupPowers.ChangeIdentity |
65  GroupPowers.ChangeMedia |
66  GroupPowers.ChangeOptions |
67  GroupPowers.CreateRole |
68  GroupPowers.DeedObject |
69  GroupPowers.DeleteRole |
70  GroupPowers.Eject |
71  GroupPowers.FindPlaces |
72  GroupPowers.HostEvent |
73  GroupPowers.Invite |
74  GroupPowers.JoinChat |
75  GroupPowers.LandChangeIdentity |
76  GroupPowers.LandDeed |
77  GroupPowers.LandDivideJoin |
78  GroupPowers.LandEdit |
79  GroupPowers.LandEjectAndFreeze |
80  GroupPowers.LandGardening |
81  GroupPowers.LandManageAllowed |
82  GroupPowers.LandManageBanned |
83  GroupPowers.LandManagePasses |
84  GroupPowers.LandOptions |
85  GroupPowers.LandRelease |
86  GroupPowers.LandSetSale |
87  GroupPowers.ModerateChat |
88  GroupPowers.ObjectManipulate |
89  GroupPowers.ObjectSetForSale |
90  GroupPowers.ReceiveNotices |
91  GroupPowers.RemoveMember |
92  GroupPowers.ReturnGroupOwned |
93  GroupPowers.ReturnGroupSet |
94  GroupPowers.ReturnNonGroup |
95  GroupPowers.RoleProperties |
96  GroupPowers.SendNotices |
97  GroupPowers.SetLandingPoint |
98  GroupPowers.StartProposal |
99  GroupPowers.VoteOnProposal;
100 
101  #region Daily Cleanup
102 
103  private Timer m_CleanupTimer;
104 
105  public GroupsService(IConfigSource config, string configName)
106  : base(config, configName)
107  {
108  }
109 
110  public GroupsService(IConfigSource config)
111  : this(config, string.Empty)
112  {
113  // Once a day
114  m_CleanupTimer = new Timer(24 * 60 * 60 * 1000);
115  m_CleanupTimer.AutoReset = true;
116  m_CleanupTimer.Elapsed += new ElapsedEventHandler(m_CleanupTimer_Elapsed);
117  m_CleanupTimer.Enabled = true;
118  m_CleanupTimer.Start();
119  }
120 
121  private void m_CleanupTimer_Elapsed(object sender, ElapsedEventArgs e)
122  {
123  m_Database.DeleteOldNotices();
124  m_Database.DeleteOldInvites();
125  }
126 
127  #endregion
128 
129  public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
130  bool allowPublish, bool maturePublish, UUID founderID, out string reason)
131  {
132  reason = string.Empty;
133 
134  // Check if the group already exists
135  if (m_Database.RetrieveGroup(name) != null)
136  {
137  reason = "A group with that name already exists";
138  return UUID.Zero;
139  }
140 
141  // Create the group
142  GroupData data = new GroupData();
143  data.GroupID = UUID.Random();
144  data.Data = new Dictionary<string, string>();
145  data.Data["Name"] = name;
146  data.Data["Charter"] = charter;
147  data.Data["InsigniaID"] = insigniaID.ToString();
148  data.Data["FounderID"] = founderID.ToString();
149  data.Data["MembershipFee"] = membershipFee.ToString();
150  data.Data["OpenEnrollment"] = openEnrollment ? "1" : "0";
151  data.Data["ShowInList"] = showInList ? "1" : "0";
152  data.Data["AllowPublish"] = allowPublish ? "1" : "0";
153  data.Data["MaturePublish"] = maturePublish ? "1" : "0";
154  UUID roleID = UUID.Random();
155  data.Data["OwnerRoleID"] = roleID.ToString();
156 
157  if (!m_Database.StoreGroup(data))
158  return UUID.Zero;
159 
160  // Create Everyone role
161  _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true);
162 
163  // Create Owner role
164  _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true);
165 
166  // Add founder to group
167  _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID);
168 
169  return data.GroupID;
170  }
171 
172  public void UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
173  {
174  GroupData data = m_Database.RetrieveGroup(groupID);
175  if (data == null)
176  return;
177 
178  // Check perms
179  if (!HasPower(RequestingAgentID, groupID, GroupPowers.ChangeActions))
180  {
181  m_log.DebugFormat("[Groups]: ({0}) Attempt at updating group {1} denied because of lack of permission", RequestingAgentID, groupID);
182  return;
183  }
184 
185  data.GroupID = groupID;
186  data.Data["Charter"] = charter;
187  data.Data["ShowInList"] = showInList ? "1" : "0";
188  data.Data["InsigniaID"] = insigniaID.ToString();
189  data.Data["MembershipFee"] = membershipFee.ToString();
190  data.Data["OpenEnrollment"] = openEnrollment ? "1" : "0";
191  data.Data["AllowPublish"] = allowPublish ? "1" : "0";
192  data.Data["MaturePublish"] = maturePublish ? "1" : "0";
193 
194  m_Database.StoreGroup(data);
195 
196  }
197 
198  public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID)
199  {
200  GroupData data = m_Database.RetrieveGroup(GroupID);
201 
202  return _GroupDataToRecord(data);
203  }
204 
205  public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, string GroupName)
206  {
207  GroupData data = m_Database.RetrieveGroup(GroupName);
208 
209  return _GroupDataToRecord(data);
210  }
211 
212  public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
213  {
214  List<DirGroupsReplyData> groups = new List<DirGroupsReplyData>();
215 
216  GroupData[] data = m_Database.RetrieveGroups(search);
217 
218  if (data != null && data.Length > 0)
219  {
220  foreach (GroupData d in data)
221  {
222  // Don't list group proxies
223  if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty)
224  continue;
225 
227  g.groupID = d.GroupID;
228 
229  if (d.Data.ContainsKey("Name"))
230  g.groupName = d.Data["Name"];
231  else
232  m_log.DebugFormat("[Groups]: Key Name not found");
233 
234  g.members = m_Database.MemberCount(d.GroupID);
235 
236  groups.Add(g);
237  }
238  }
239 
240  return groups;
241  }
242 
243  public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
244  {
245  List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
246 
247  GroupData group = m_Database.RetrieveGroup(GroupID);
248  if (group == null)
249  return members;
250 
251  // Unfortunately this doesn't quite work on legacy group data because of a bug
252  // that's also being fixed here on CreateGroup. The OwnerRoleID sent to the DB was wrong.
253  // See how to find the ownerRoleID a few lines below.
254  UUID ownerRoleID = new UUID(group.Data["OwnerRoleID"]);
255 
256  RoleData[] roles = m_Database.RetrieveRoles(GroupID);
257  if (roles == null)
258  // something wrong with this group
259  return members;
260  List<RoleData> rolesList = new List<RoleData>(roles);
261 
262  // Let's find the "real" ownerRoleID
263  RoleData ownerRole = rolesList.Find(r => r.Data["Powers"] == ((long)OwnerPowers).ToString());
264  if (ownerRole != null)
265  ownerRoleID = ownerRole.RoleID;
266 
267  // Check visibility?
268  // When we don't want to check visibility, we pass it "all" as the requestingAgentID
269  bool checkVisibility = !RequestingAgentID.Equals(UUID.Zero.ToString());
270 
271  if (checkVisibility)
272  {
273  // Is the requester a member of the group?
274  bool isInGroup = false;
275  if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
276  isInGroup = true;
277 
278  if (!isInGroup) // reduce the roles to the visible ones
279  rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
280  }
281 
282  MembershipData[] datas = m_Database.RetrieveMembers(GroupID);
283  if (datas == null || (datas != null && datas.Length == 0))
284  return members;
285 
286  // OK, we have everything we need
287 
288  foreach (MembershipData d in datas)
289  {
290  RoleMembershipData[] rolememberships = m_Database.RetrieveMemberRoles(GroupID, d.PrincipalID);
291  List<RoleMembershipData> rolemembershipsList = new List<RoleMembershipData>(rolememberships);
292 
294 
295  // What's this person's current role in the group?
296  UUID selectedRole = new UUID(d.Data["SelectedRoleID"]);
297  RoleData selected = rolesList.Find(r => r.RoleID == selectedRole);
298 
299  if (selected != null)
300  {
301  m.Title = selected.Data["Title"];
302  m.AgentPowers = UInt64.Parse(selected.Data["Powers"]);
303  }
304 
305  m.AgentID = d.PrincipalID;
306  m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false;
307  m.Contribution = Int32.Parse(d.Data["Contribution"]);
308  m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false;
309 
310  GridUserData gud = m_GridUserService.Get(d.PrincipalID);
311  if (gud != null)
312  {
313  if (bool.Parse(gud.Data["Online"]))
314  {
315  m.OnlineStatus = @"Online";
316  }
317  else
318  {
319  int unixtime = int.Parse(gud.Data["Login"]);
320  // The viewer is very picky about how these strings are formed. Eg. it will crash on malformed dates!
321  m.OnlineStatus = (unixtime == 0) ? @"unknown" : Util.ToDateTime(unixtime).ToString("MM/dd/yyyy");
322  }
323  }
324 
325  // Is this person an owner of the group?
326  m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false;
327 
328  members.Add(m);
329  }
330 
331  return members;
332  }
333 
334  public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
335  {
336  reason = string.Empty;
337  // check that the requesting agent has permissions to add role
338  if (!HasPower(RequestingAgentID, groupID, GroupPowers.CreateRole))
339  {
340  m_log.DebugFormat("[Groups]: ({0}) Attempt at creating role in group {1} denied because of lack of permission", RequestingAgentID, groupID);
341  reason = "Insufficient permission to create role";
342  return false;
343  }
344 
345  return _AddOrUpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, true);
346 
347  }
348 
349  public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
350  {
351  // check perms
352  if (!HasPower(RequestingAgentID, groupID, GroupPowers.ChangeActions))
353  {
354  m_log.DebugFormat("[Groups]: ({0}) Attempt at changing role in group {1} denied because of lack of permission", RequestingAgentID, groupID);
355  return false;
356  }
357 
358  return _AddOrUpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, false);
359  }
360 
361  public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
362  {
363  // check perms
364  if (!HasPower(RequestingAgentID, groupID, GroupPowers.DeleteRole))
365  {
366  m_log.DebugFormat("[Groups]: ({0}) Attempt at deleting role from group {1} denied because of lack of permission", RequestingAgentID, groupID);
367  return;
368  }
369 
370  // Can't delete Everyone and Owners roles
371  if (roleID == UUID.Zero)
372  {
373  m_log.DebugFormat("[Groups]: Attempt at deleting Everyone role from group {0} denied", groupID);
374  return;
375  }
376 
377  GroupData group = m_Database.RetrieveGroup(groupID);
378  if (group == null)
379  {
380  m_log.DebugFormat("[Groups]: Attempt at deleting role from non-existing group {0}", groupID);
381  return;
382  }
383 
384  if (roleID == new UUID(group.Data["OwnerRoleID"]))
385  {
386  m_log.DebugFormat("[Groups]: Attempt at deleting Owners role from group {0} denied", groupID);
387  return;
388  }
389 
390  _RemoveGroupRole(groupID, roleID);
391  }
392 
393  public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
394  {
395  // TODO: check perms
396  return _GetGroupRoles(GroupID);
397  }
398 
399  public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
400  {
401  // TODO: check perms
402 
403  // Is the requester a member of the group?
404  bool isInGroup = false;
405  if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
406  isInGroup = true;
407 
408  return _GetGroupRoleMembers(GroupID, isInGroup);
409  }
410 
411  public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
412  {
413  reason = string.Empty;
414 
415  _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token);
416 
417  return true;
418  }
419 
420  public bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
421  {
422  // check perms
423  if (RequestingAgentID != AgentID && !HasPower(RequestingAgentID, GroupID, GroupPowers.Eject))
424  return false;
425 
426  _RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
427 
428  return true;
429  }
430 
431  public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
432  {
433  // Check whether the invitee is already a member of the group
434  MembershipData m = m_Database.RetrieveMember(groupID, agentID);
435  if (m != null)
436  return false;
437 
438  // Check permission to invite
439  if (!HasPower(RequestingAgentID, groupID, GroupPowers.Invite))
440  {
441  m_log.DebugFormat("[Groups]: ({0}) Attempt at inviting to group {1} denied because of lack of permission", RequestingAgentID, groupID);
442  return false;
443  }
444 
445  // Check whether there are pending invitations and delete them
446  InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID);
447  if (invite != null)
448  m_Database.DeleteInvite(invite.InviteID);
449 
450  invite = new InvitationData();
451  invite.InviteID = inviteID;
452  invite.PrincipalID = agentID;
453  invite.GroupID = groupID;
454  invite.RoleID = roleID;
455  invite.Data = new Dictionary<string, string>();
456 
457  return m_Database.StoreInvitation(invite);
458  }
459 
460  public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
461  {
462  InvitationData data = m_Database.RetrieveInvitation(inviteID);
463 
464  if (data == null)
465  return null;
466 
467  GroupInviteInfo inviteInfo = new GroupInviteInfo();
468  inviteInfo.AgentID = data.PrincipalID;
469  inviteInfo.GroupID = data.GroupID;
470  inviteInfo.InviteID = data.InviteID;
471  inviteInfo.RoleID = data.RoleID;
472 
473  return inviteInfo;
474  }
475 
476  public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
477  {
478  m_Database.DeleteInvite(inviteID);
479  }
480 
481  public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
482  {
483  //if (!m_Database.CheckOwnerRole(RequestingAgentID, GroupID, RoleID))
484  // return;
485 
486  // check permissions
487  bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited);
488  bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID);
489  if (!limited || !unlimited)
490  {
491  m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
492  return false;
493  }
494 
495  // AssignMemberLimited means that the person can assign another person to the same roles that she has in the group
496  if (!unlimited && limited)
497  {
498  // check whether person's has this role
499  RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
500  if (rolemembership == null)
501  {
502  m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID);
503  return false;
504  }
505  }
506 
507  _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
508 
509  return true;
510  }
511 
512  public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
513  {
514  // Don't remove from Everyone role!
515  if (RoleID == UUID.Zero)
516  return false;
517 
518  // check permissions
519  bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID);
520  if (!unlimited)
521  {
522  m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
523  return false;
524  }
525 
526  RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
527 
528  if (rolemember == null)
529  return false;
530 
531  m_Database.DeleteRoleMember(rolemember);
532 
533  // Find another role for this person
534  UUID newRoleID = UUID.Zero; // Everyone
535  RoleMembershipData[] rdata = m_Database.RetrieveMemberRoles(GroupID, AgentID);
536  if (rdata != null)
537  foreach (RoleMembershipData r in rdata)
538  {
539  if (r.RoleID != UUID.Zero)
540  {
541  newRoleID = r.RoleID;
542  break;
543  }
544  }
545 
546  MembershipData member = m_Database.RetrieveMember(GroupID, AgentID);
547  if (member != null)
548  {
549  member.Data["SelectedRoleID"] = newRoleID.ToString();
550  m_Database.StoreMember(member);
551  }
552 
553  return true;
554  }
555 
556  public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
557  {
558  List<GroupRolesData> roles = new List<GroupRolesData>();
559  // TODO: check permissions
560 
561  RoleMembershipData[] data = m_Database.RetrieveMemberRoles(GroupID, AgentID);
562  if (data == null || (data != null && data.Length ==0))
563  return roles;
564 
565  foreach (RoleMembershipData d in data)
566  {
567  RoleData rdata = m_Database.RetrieveRole(GroupID, d.RoleID);
568  if (rdata == null) // hippos
569  continue;
570 
571  GroupRolesData r = new GroupRolesData();
572  r.Name = rdata.Data["Name"];
573  r.Powers = UInt64.Parse(rdata.Data["Powers"]);
574  r.RoleID = rdata.RoleID;
575  r.Title = rdata.Data["Title"];
576 
577  roles.Add(r);
578  }
579 
580  return roles;
581  }
582 
583  public ExtendedGroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
584  {
585  // TODO: check perms
586  PrincipalData principal = new PrincipalData();
587  principal.PrincipalID = AgentID;
588  principal.ActiveGroupID = GroupID;
589  m_Database.StorePrincipal(principal);
590 
591  return GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID);
592  }
593 
594  public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
595  {
596  // 1. get the principal data for the active group
597  PrincipalData principal = m_Database.RetrievePrincipal(AgentID);
598  if (principal == null)
599  return null;
600 
601  return GetAgentGroupMembership(RequestingAgentID, AgentID, principal.ActiveGroupID);
602  }
603 
604  public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
605  {
606  return GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID, null);
607  }
608 
609  private ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID, MembershipData membership)
610  {
611  // 2. get the active group
612  GroupData group = m_Database.RetrieveGroup(GroupID);
613  if (group == null)
614  return null;
615 
616  // 3. get the membership info if we don't have it already
617  if (membership == null)
618  {
619  membership = m_Database.RetrieveMember(group.GroupID, AgentID);
620  if (membership == null)
621  return null;
622  }
623 
624  // 4. get the active role
625  UUID activeRoleID = new UUID(membership.Data["SelectedRoleID"]);
626  RoleData role = m_Database.RetrieveRole(group.GroupID, activeRoleID);
627 
628  ExtendedGroupMembershipData data = new ExtendedGroupMembershipData();
629  data.AcceptNotices = membership.Data["AcceptNotices"] == "1" ? true : false;
630  data.AccessToken = membership.Data["AccessToken"];
631  data.Active = true;
632  data.ActiveRole = activeRoleID;
633  data.AllowPublish = group.Data["AllowPublish"] == "1" ? true : false;
634  data.Charter = group.Data["Charter"];
635  data.Contribution = Int32.Parse(membership.Data["Contribution"]);
636  data.FounderID = new UUID(group.Data["FounderID"]);
637  data.GroupID = new UUID(group.GroupID);
638  data.GroupName = group.Data["Name"];
639  data.GroupPicture = new UUID(group.Data["InsigniaID"]);
640  if (role != null)
641  {
642  data.GroupPowers = UInt64.Parse(role.Data["Powers"]);
643  data.GroupTitle = role.Data["Title"];
644  }
645  data.ListInProfile = membership.Data["ListInProfile"] == "1" ? true : false;
646  data.MaturePublish = group.Data["MaturePublish"] == "1" ? true : false;
647  data.MembershipFee = Int32.Parse(group.Data["MembershipFee"]);
648  data.OpenEnrollment = group.Data["OpenEnrollment"] == "1" ? true : false;
649  data.ShowInList = group.Data["ShowInList"] == "1" ? true : false;
650 
651  return data;
652  }
653 
654  public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
655  {
656  List<GroupMembershipData> memberships = new List<GroupMembershipData>();
657 
658  // 1. Get all the groups that this person is a member of
659  MembershipData[] mdata = m_Database.RetrieveMemberships(AgentID);
660 
661  if (mdata == null || (mdata != null && mdata.Length == 0))
662  return memberships;
663 
664  foreach (MembershipData d in mdata)
665  {
666  GroupMembershipData gmember = GetAgentGroupMembership(RequestingAgentID, AgentID, d.GroupID, d);
667  if (gmember != null)
668  {
669  memberships.Add(gmember);
670  //m_log.DebugFormat("[XXX]: Member of {0} as {1}", gmember.GroupName, gmember.GroupTitle);
671  //Util.PrintCallStack();
672  }
673  }
674 
675  return memberships;
676  }
677 
678  public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
679  {
680  MembershipData data = m_Database.RetrieveMember(GroupID, AgentID);
681  if (data == null)
682  return;
683 
684  data.Data["SelectedRoleID"] = RoleID.ToString();
685  m_Database.StoreMember(data);
686  }
687 
688  public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
689  {
690  // TODO: check perms
691 
692  MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
693  if (membership == null)
694  return;
695 
696  membership.Data["AcceptNotices"] = AcceptNotices ? "1" : "0";
697  membership.Data["ListInProfile"] = ListInProfile ? "1" : "0";
698 
699  m_Database.StoreMember(membership);
700  }
701 
702  public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
703  bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
704  {
705  // Check perms
706  if (!HasPower(RequestingAgentID, groupID, GroupPowers.SendNotices))
707  {
708  m_log.DebugFormat("[Groups]: ({0}) Attempt at sending notice to group {1} denied because of lack of permission", RequestingAgentID, groupID);
709  return false;
710  }
711 
712  return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID);
713  }
714 
715  public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
716  {
717  NoticeData data = m_Database.RetrieveNotice(noticeID);
718 
719  if (data == null)
720  return null;
721 
722  return _NoticeDataToInfo(data);
723  }
724 
725  public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID groupID)
726  {
727  NoticeData[] data = m_Database.RetrieveNotices(groupID);
728  List<ExtendedGroupNoticeData> infos = new List<ExtendedGroupNoticeData>();
729 
730  if (data == null || (data != null && data.Length == 0))
731  return infos;
732 
733  foreach (NoticeData d in data)
734  {
735  ExtendedGroupNoticeData info = _NoticeDataToData(d);
736  infos.Add(info);
737  }
738 
739  return infos;
740  }
741 
742  public void ResetAgentGroupChatSessions(string agentID)
743  {
744  }
745 
746  public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
747  {
748  return false;
749  }
750 
751  public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
752  {
753  return false;
754  }
755 
756  public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
757  {
758  }
759 
760  public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
761  {
762  }
763 
764  #region Actions without permission checks
765 
766  protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
767  {
768  _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, string.Empty);
769  }
770 
771  protected void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
772  {
773  // 1. Delete membership
774  m_Database.DeleteMember(GroupID, AgentID);
775 
776  // 2. Remove from rolememberships
777  m_Database.DeleteMemberAllRoles(GroupID, AgentID);
778 
779  // 3. if it was active group, inactivate it
780  PrincipalData principal = m_Database.RetrievePrincipal(AgentID);
781  if (principal != null && principal.ActiveGroupID == GroupID)
782  {
783  principal.ActiveGroupID = UUID.Zero;
784  m_Database.StorePrincipal(principal);
785  }
786  }
787 
788  protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string accessToken)
789  {
790  // Check if it's already there
791  MembershipData data = m_Database.RetrieveMember(GroupID, AgentID);
792  if (data != null)
793  return;
794 
795  // Add the membership
796  data = new MembershipData();
797  data.PrincipalID = AgentID;
798  data.GroupID = GroupID;
799  data.Data = new Dictionary<string, string>();
800  data.Data["SelectedRoleID"] = RoleID.ToString();
801  data.Data["Contribution"] = "0";
802  data.Data["ListInProfile"] = "1";
803  data.Data["AcceptNotices"] = "1";
804  data.Data["AccessToken"] = accessToken;
805 
806  m_Database.StoreMember(data);
807 
808  // Add principal to everyone role
809  _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, UUID.Zero);
810 
811  // Add principal to role, if different from everyone role
812  if (RoleID != UUID.Zero)
813  _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
814 
815  // Make thit this active group
816  PrincipalData pdata = new PrincipalData();
817  pdata.PrincipalID = AgentID;
818  pdata.ActiveGroupID = GroupID;
819  m_Database.StorePrincipal(pdata);
820 
821  }
822 
823  protected bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
824  {
825  RoleData data = m_Database.RetrieveRole(groupID, roleID);
826 
827  if (add && data != null) // it already exists, can't create
828  {
829  m_log.DebugFormat("[Groups]: Group {0} already exists. Can't create it again", groupID);
830  return false;
831  }
832 
833  if (!add && data == null) // it deosn't exist, can't update
834  {
835  m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID);
836  return false;
837  }
838 
839  if (add)
840  data = new RoleData();
841 
842  data.GroupID = groupID;
843  data.RoleID = roleID;
844  data.Data = new Dictionary<string, string>();
845  data.Data["Name"] = name;
846  data.Data["Description"] = description;
847  data.Data["Title"] = title;
848  data.Data["Powers"] = powers.ToString();
849 
850  return m_Database.StoreRole(data);
851  }
852 
853  protected void _RemoveGroupRole(UUID groupID, UUID roleID)
854  {
855  m_Database.DeleteRole(groupID, roleID);
856  }
857 
858  protected void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
859  {
860  RoleMembershipData data = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
861  if (data != null)
862  return;
863 
864  data = new RoleMembershipData();
865  data.GroupID = GroupID;
866  data.PrincipalID = AgentID;
867  data.RoleID = RoleID;
868  m_Database.StoreRoleMember(data);
869 
870  // Make it the SelectedRoleID
871  MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
872  if (membership == null)
873  {
874  m_log.DebugFormat("[Groups]: ({0}) No such member {0} in group {1}", AgentID, GroupID);
875  return;
876  }
877 
878  membership.Data["SelectedRoleID"] = RoleID.ToString();
879  m_Database.StoreMember(membership);
880 
881  }
882 
883  protected List<GroupRolesData> _GetGroupRoles(UUID groupID)
884  {
885  List<GroupRolesData> roles = new List<GroupRolesData>();
886 
887  RoleData[] data = m_Database.RetrieveRoles(groupID);
888 
889  if (data == null || (data != null && data.Length == 0))
890  return roles;
891 
892  foreach (RoleData d in data)
893  {
894  GroupRolesData r = new GroupRolesData();
895  r.Description = d.Data["Description"];
896  r.Members = m_Database.RoleMemberCount(groupID, d.RoleID);
897  r.Name = d.Data["Name"];
898  r.Powers = UInt64.Parse(d.Data["Powers"]);
899  r.RoleID = d.RoleID;
900  r.Title = d.Data["Title"];
901 
902  roles.Add(r);
903  }
904 
905  return roles;
906  }
907 
908  protected List<ExtendedGroupRoleMembersData> _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
909  {
910  List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
911 
912  RoleData[] rdata = new RoleData[0];
913  if (!isInGroup)
914  {
915  rdata = m_Database.RetrieveRoles(GroupID);
916  if (rdata == null || (rdata != null && rdata.Length == 0))
917  return rmembers;
918  }
919  List<RoleData> rlist = new List<RoleData>(rdata);
920  if (!isInGroup)
921  rlist = rlist.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
922 
923  RoleMembershipData[] data = m_Database.RetrieveRolesMembers(GroupID);
924 
925  if (data == null || (data != null && data.Length == 0))
926  return rmembers;
927 
928  foreach (RoleMembershipData d in data)
929  {
930  if (!isInGroup)
931  {
932  RoleData rd = rlist.Find(_r => _r.RoleID == d.RoleID); // visible role
933  if (rd == null)
934  continue;
935  }
936 
938  r.MemberID = d.PrincipalID;
939  r.RoleID = d.RoleID;
940 
941  rmembers.Add(r);
942  }
943 
944  return rmembers;
945  }
946 
947  protected bool _AddNotice(UUID groupID, UUID noticeID, string fromName, string subject, string message,
948  bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
949  {
950  NoticeData data = new NoticeData();
951  data.GroupID = groupID;
952  data.NoticeID = noticeID;
953  data.Data = new Dictionary<string, string>();
954  data.Data["FromName"] = fromName;
955  data.Data["Subject"] = subject;
956  data.Data["Message"] = message;
957  data.Data["HasAttachment"] = hasAttachment ? "1" : "0";
958  if (hasAttachment)
959  {
960  data.Data["AttachmentType"] = attType.ToString();
961  data.Data["AttachmentName"] = attName;
962  data.Data["AttachmentItemID"] = attItemID.ToString();
963  data.Data["AttachmentOwnerID"] = attOwnerID;
964  }
965  data.Data["TMStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString();
966 
967  return m_Database.StoreNotice(data);
968  }
969 
970  #endregion
971 
972  #region structure translations
973  ExtendedGroupRecord _GroupDataToRecord(GroupData data)
974  {
975  if (data == null)
976  return null;
977 
979  rec.AllowPublish = data.Data["AllowPublish"] == "1" ? true : false;
980  rec.Charter = data.Data["Charter"];
981  rec.FounderID = new UUID(data.Data["FounderID"]);
982  rec.GroupID = data.GroupID;
983  rec.GroupName = data.Data["Name"];
984  rec.GroupPicture = new UUID(data.Data["InsigniaID"]);
985  rec.MaturePublish = data.Data["MaturePublish"] == "1" ? true : false;
986  rec.MembershipFee = Int32.Parse(data.Data["MembershipFee"]);
987  rec.OpenEnrollment = data.Data["OpenEnrollment"] == "1" ? true : false;
988  rec.OwnerRoleID = new UUID(data.Data["OwnerRoleID"]);
989  rec.ShowInList = data.Data["ShowInList"] == "1" ? true : false;
990  rec.ServiceLocation = data.Data["Location"];
991  rec.MemberCount = m_Database.MemberCount(data.GroupID);
992  rec.RoleCount = m_Database.RoleCount(data.GroupID);
993 
994  return rec;
995  }
996 
997  GroupNoticeInfo _NoticeDataToInfo(NoticeData data)
998  {
999  GroupNoticeInfo notice = new GroupNoticeInfo();
1000  notice.GroupID = data.GroupID;
1001  notice.Message = data.Data["Message"];
1002  notice.noticeData = _NoticeDataToData(data);
1003 
1004  return notice;
1005  }
1006 
1007  ExtendedGroupNoticeData _NoticeDataToData(NoticeData data)
1008  {
1009  ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData();
1010  notice.FromName = data.Data["FromName"];
1011  notice.NoticeID = data.NoticeID;
1012  notice.Subject = data.Data["Subject"];
1013  notice.Timestamp = uint.Parse((string)data.Data["TMStamp"]);
1014  notice.HasAttachment = data.Data["HasAttachment"] == "1" ? true : false;
1015  if (notice.HasAttachment)
1016  {
1017  notice.AttachmentName = data.Data["AttachmentName"];
1018  notice.AttachmentItemID = new UUID(data.Data["AttachmentItemID"].ToString());
1019  notice.AttachmentType = byte.Parse(data.Data["AttachmentType"].ToString());
1020  notice.AttachmentOwnerID = data.Data["AttachmentOwnerID"].ToString();
1021  }
1022 
1023 
1024  return notice;
1025  }
1026 
1027  #endregion
1028 
1029  #region permissions
1030  private bool HasPower(string agentID, UUID groupID, GroupPowers power)
1031  {
1032  RoleMembershipData[] rmembership = m_Database.RetrieveMemberRoles(groupID, agentID);
1033  if (rmembership == null || (rmembership != null && rmembership.Length == 0))
1034  return false;
1035 
1036  foreach (RoleMembershipData rdata in rmembership)
1037  {
1038  RoleData role = m_Database.RetrieveRole(groupID, rdata.RoleID);
1039  if ( (UInt64.Parse(role.Data["Powers"]) & (ulong)power) != 0 )
1040  return true;
1041  }
1042  return false;
1043  }
1044 
1045  private bool IsOwner(string agentID, UUID groupID)
1046  {
1047  GroupData group = m_Database.RetrieveGroup(groupID);
1048  if (group == null)
1049  return false;
1050 
1051  RoleMembershipData rmembership = m_Database.RetrieveRoleMember(groupID, new UUID(group.Data["OwnerRoleID"]), agentID);
1052  if (rmembership == null)
1053  return false;
1054 
1055  return true;
1056  }
1057  #endregion
1058 
1059  }
1060 }
GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
List< GroupMembershipData > GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
void UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
Dictionary< string, string > Data
bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
Dictionary< string, string > Data
Definition: IGroupsData.cs:80
UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason)
ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, string GroupName)
void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
List< ExtendedGroupMembersData > GetGroupMembers(string RequestingAgentID, UUID GroupID)
Dictionary< string, string > Data
Definition: IGroupsData.cs:37
System.Timers.Timer Timer
List< ExtendedGroupNoticeData > GetGroupNotices(string RequestingAgentID, UUID groupID)
ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
void _RemoveGroupRole(UUID groupID, UUID roleID)
bool _AddNotice(UUID groupID, UUID noticeID, string fromName, string subject, string message, bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
GroupsService(IConfigSource config)
List< DirGroupsReplyData > FindGroups(string RequestingAgentID, string search)
List< ExtendedGroupRoleMembersData > _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
List< GroupRolesData > GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
List< GroupRolesData > _GetGroupRoles(UUID groupID)
bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID)
void ResetAgentGroupChatSessions(string agentID)
void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
ExtendedGroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
List< ExtendedGroupRoleMembersData > GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string accessToken)
bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
Dictionary< string, string > Data
Definition: IGroupsData.cs:44
void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
bool RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
List< GroupRolesData > GetGroupRoles(string RequestingAgentID, UUID GroupID)
ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
GroupsService(IConfigSource config, string configName)
Dictionary< string, string > Data
Definition: IGroupsData.cs:51