clockwerk-opensim – Blame information for rev 1

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